diff --git a/example/pass_strength/pass_strength.go b/example/pass_strength/pass_strength.go new file mode 100644 index 0000000..afcef45 --- /dev/null +++ b/example/pass_strength/pass_strength.go @@ -0,0 +1,102 @@ +// 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 +// +// 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)) +}