| // 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)) |
| } |