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  }