forked from mirror/readline
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
|
// This is a small example using readline to read a password
|
||
|
// and check it's strength while typing using the zxcvbn library.
|
||
|
// Depending on the strength the prompt is colored nicely to indicate strength.
|
||
|
//
|
||
|
// This file is licensed under the WTFPL:
|
||
|
//
|
||
|
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||
|
// Version 2, December 2004
|
||
|
//
|
||
|
// Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||
|
//
|
||
|
// Everyone is permitted to copy and distribute verbatim or modified
|
||
|
// copies of this license document, and changing it is allowed as long
|
||
|
// as the name is changed.
|
||
|
//
|
||
|
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||
|
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||
|
//
|
||
|
// 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/chzyer/readline"
|
||
|
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
Cyan = 36
|
||
|
Green = 32
|
||
|
Magenta = 35
|
||
|
Red = 31
|
||
|
Yellow = 33
|
||
|
BackgroundRed = 41
|
||
|
)
|
||
|
|
||
|
// Reset sequence
|
||
|
var ColorResetEscape = "\033[0m"
|
||
|
|
||
|
// ColorResetEscape translates a ANSI color number to a color escape.
|
||
|
func ColorEscape(color int) string {
|
||
|
return fmt.Sprintf("\033[0;%dm", color)
|
||
|
}
|
||
|
|
||
|
// Colorize the msg using ANSI color escapes
|
||
|
func Colorize(msg string, color int) string {
|
||
|
return ColorEscape(color) + msg + ColorResetEscape
|
||
|
}
|
||
|
|
||
|
func createStrengthPrompt(password []rune) string {
|
||
|
symbol, color := "", Red
|
||
|
strength := zxcvbn.PasswordStrength(string(password), nil)
|
||
|
|
||
|
switch {
|
||
|
case strength.Score <= 1:
|
||
|
symbol = "✗"
|
||
|
color = Red
|
||
|
case strength.Score <= 2:
|
||
|
symbol = "⚡"
|
||
|
color = Magenta
|
||
|
case strength.Score <= 3:
|
||
|
symbol = "⚠"
|
||
|
color = Yellow
|
||
|
case strength.Score <= 4:
|
||
|
symbol = "✔"
|
||
|
color = Green
|
||
|
}
|
||
|
|
||
|
prompt := Colorize(symbol, color)
|
||
|
if strength.Entropy > 0 {
|
||
|
entropy := fmt.Sprintf(" %3.0f", strength.Entropy)
|
||
|
prompt += Colorize(entropy, Cyan)
|
||
|
} else {
|
||
|
prompt += Colorize(" ENT", Cyan)
|
||
|
}
|
||
|
|
||
|
prompt += Colorize(" New Password: ", color)
|
||
|
return prompt
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
rl, err := readline.New("")
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer rl.Close()
|
||
|
|
||
|
setPasswordCfg := rl.GenPasswordConfig()
|
||
|
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
||
|
rl.SetPrompt(createStrengthPrompt(line))
|
||
|
rl.Refresh()
|
||
|
return nil, 0, false
|
||
|
})
|
||
|
|
||
|
pswd, err := rl.ReadPasswordWithConfig(setPasswordCfg)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
fmt.Println("Your password was:", string(pswd))
|
||
|
}
|