github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/apps/pwdgen/pwdgen.go (about) 1 // Copyright 2012 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Password generator 6 // 7 // Usage: 8 // pwdgen [options]... [id]... 9 // 10 // Algorithm: 11 // base58(sha512(md5hex(encrypt_key+encrypt_salt)+site_id+site_salt)[0:16] 12 // 13 // Example: 14 // pwdgen id0 15 // pwdgen id0 id1 id2 16 // 17 // pwdgen --encrypt-key=111 id0 18 // pwdgen --encrypt-key=111 id0 id1 id2 19 // 20 // pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 21 // pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 22 // pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 23 // 24 // # KeePass: See config.ini 25 // # output: *.ini -> *.keepass1x.csv 26 // pwdgen --keepass-config=config.ini 27 // pwdgen --keepass-config=config.ini --encrypt-key=111 28 // pwdgen --keepass-config=config.ini --encrypt-key=111 --encrypt-salt=fuckcsdn 29 // 30 // pwdgen --version 31 // pwdgen --help 32 // pwdgen -h 33 // 34 // Use pwdgen as a Go package: 35 // package main 36 // 37 // import ( 38 // "fmt" 39 // pwdgen "bitbucket.org/chai2010/pwdgen" 40 // ) 41 // func main() { 42 // fmt.Println(pwdgen.PwdGen("id0", "site0", "111", "fuckcsdn")) 43 // // Output: 2jNXfMGoXTSK9pFS 44 // } 45 // 46 // Report bugs to <chaishushan{AT}gmail.com>. 47 package main 48 49 import ( 50 "bufio" 51 "crypto/md5" 52 "crypto/sha512" 53 "flag" 54 "fmt" 55 "os" 56 "strings" 57 58 "github.com/chai2010/gopkg/encoding/base58" 59 "github.com/chai2010/gopkg/encoding/ini" 60 ) 61 62 const ( 63 majorVersion = 2 64 minorVersion = 4 65 ) 66 67 var ( 68 encrypt_key = flag.String("encrypt-key", "", "Set encrypt key.") 69 encrypt_salt = flag.String("encrypt-salt", "", "Set encrypt salt.") 70 site_salt = flag.String("site-salt", "", "Set site salt.") 71 72 keepass_config = flag.String("keepass-config", "", "Generate KeePass 1.x CSV.") 73 74 version = flag.Bool("version", false, "Show version and exit.") 75 help = flag.Bool("help", false, "Show usage and exit.") 76 ) 77 78 func init() { 79 flag.Usage = func() { 80 fmt.Fprintf(os.Stderr, "Usage: pwdgen [options]... [id]...\n") 81 flag.PrintDefaults() 82 fmt.Fprintf(os.Stderr, "%s\n", ` 83 Algorithm: 84 base58(sha512(md5hex(encrypt_key+encrypt_salt)+site_id+site_salt)[0:16] 85 86 Example: 87 pwdgen id0 88 pwdgen id0 id1 id2 89 90 pwdgen --encrypt-key=111 id0 91 pwdgen --encrypt-key=111 id0 id1 id2 92 93 pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 94 pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 95 pwdgen --encrypt-key=111 --encrypt-salt=fuckcsdn --site-salt=site0 id0 id1 96 97 # KeePass: See config.ini 98 # output: *.ini -> *.keepass1x.csv 99 pwdgen --keepass-config=config.ini 100 pwdgen --keepass-config=config.ini --encrypt-key=111 101 pwdgen --keepass-config=config.ini --encrypt-key=111 --encrypt-salt=fuckcsdn 102 103 pwdgen --version 104 pwdgen --help 105 pwdgen -h 106 107 Use pwdgen as a Go package: 108 package main 109 110 import ( 111 "fmt" 112 pwdgen "bitbucket.org/chai2010/pwdgen" 113 ) 114 func main() { 115 fmt.Println(pwdgen.PwdGen("id0", "site0", "111", "fuckcsdn")) 116 // Output: 2jNXfMGoXTSK9pFS 117 } 118 119 Report bugs to <chaishushan{AT}gmail.com>.`) 120 } 121 } 122 123 func parseCmdLine() { 124 flag.Parse() 125 126 if *version { 127 fmt.Printf("pwdgen-%d.%d\n", majorVersion, minorVersion) 128 os.Exit(0) 129 } 130 if *help { 131 flag.Usage() 132 os.Exit(0) 133 } 134 } 135 136 // base58(sha512(md5hex(encrypt_key+encrypt_salt)+site_id+site_salt)[0:16] 137 func PwdGen(site_id, site_salt, encrypt_key, encrypt_salt string) string { 138 md5 := md5.New() 139 md5.Write([]byte(encrypt_key + encrypt_salt)) 140 md5Hex := fmt.Sprintf("%x", md5.Sum(nil)) 141 142 sha := sha512.New() 143 sha.Write([]byte(md5Hex + site_id + site_salt)) 144 shaSum := sha.Sum(nil) 145 146 pwd := base58.EncodeBase58(shaSum)[0:16] 147 return string(pwd) 148 } 149 150 func main() { 151 parseCmdLine() 152 if flag.NArg() <= 0 && len(*keepass_config) <= 0 { 153 flag.Usage() 154 os.Exit(0) 155 } 156 157 if len(*encrypt_key) <= 0 { 158 fmt.Printf("Encryption key: ") 159 reader := bufio.NewReader(os.Stdin) 160 input, _ := reader.ReadString('\n') 161 (*encrypt_key) = strings.TrimSpace(input) 162 if len(*encrypt_key) <= 0 { 163 fmt.Fprintf(os.Stderr, "ERROR: Key must be at least 1 characters.\n") 164 os.Exit(-1) 165 } 166 } 167 168 if *keepass_config != "" { 169 dict, err := ini.LoadFile(*keepass_config) 170 if err != nil { 171 fmt.Fprintf(os.Stderr, "ERROR: Load <%s> failed.\n", *keepass_config) 172 os.Exit(-1) 173 } 174 175 csvName := strings.Replace(*keepass_config, ".ini", ".keepass1x.csv", -1) 176 file, err := os.Create(csvName) 177 if err != nil { 178 fmt.Fprintf(os.Stderr, "ERROR: Create <%s> failed.\n", csvName) 179 os.Exit(-1) 180 } 181 defer file.Close() 182 183 // KeePass 1.x csv head line 184 fmt.Fprintf(file, `"%s","%s","%s","%s","%s"`+"\n", 185 "Account", "Login Name", "Password", "Web Site", "Comments", 186 ) 187 188 keepass_site_list := dict.GetSections() 189 for i := 0; i < len(keepass_site_list); i++ { 190 keepass_site_name := keepass_site_list[i] 191 keepass_site_id := dict[keepass_site_name]["LoginName"] 192 keepass_site_salt := keepass_site_name + dict[keepass_site_name]["SiteSalt"] 193 keepass_site_url := dict[keepass_site_name]["WebSite"] 194 keepass_site_comments := dict[keepass_site_name]["Comments"] 195 keepass_site_pwd := PwdGen(keepass_site_id, keepass_site_salt, *encrypt_key, *encrypt_salt) 196 197 fmt.Fprintf(file, `"%s","%s","%s","%s","%s"`+"\n", 198 keepass_site_name, keepass_site_id, keepass_site_pwd, 199 keepass_site_url, keepass_site_comments, 200 ) 201 } 202 } else { 203 for i := 0; i < flag.NArg(); i++ { 204 password := PwdGen(flag.Arg(i), *site_salt, *encrypt_key, *encrypt_salt) 205 fmt.Printf("%s\n", password) 206 } 207 } 208 }