package mp import ( "crypto/hmac" "crypto/sha256" "encoding/binary" "golang.org/x/crypto/scrypt" "runtime" "sync" ) type TemplateType int const ( MaximumSecurityPassword TemplateType = iota LongPassword MediumPassword BasicPassword ShortPassword PIN Name Phrase ) const variant = "com.lyndir.masterpassword" var ( typeMap = map[TemplateType][]string{ MaximumSecurityPassword: { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno", }, LongPassword: { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno", }, MediumPassword: { "CvcnoCvc", "CvcCvcno", }, BasicPassword: { "aaanaaan", "aannaaan", "aaannaaa", }, ShortPassword: { "Cvcn", }, PIN: { "nnnn", }, Name: { "cvccvcvcv", }, Phrase: { "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv", }, } charMap = map[rune]string{ 'V': "AEIOU", 'C': "BCDFGHJKLMNPQRSTVWXYZ", 'v': "aeiou", 'c': "bcdfghjklmnpqrstvwxyz", 'A': "AEIOUBCDFGHJKLMNPQRSTVWXYZ", 'a': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz", 'n': "0123456789", 'o': "@&%?,=[]_:-+*$#!'^~;()/.", 'x': "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()", ' ': " ", } ) func i2b(i int) (b []byte) { b = make([]byte, 4) binary.BigEndian.PutUint32(b, uint32(i)) return } type MP struct { sync.Mutex key []byte } func NewMP(p, name []byte) (*MP, error) { salt := []byte(variant) salt = append(salt, i2b(len(name))...) salt = append(salt, name...) key, err := scrypt.Key(p, salt, 32768, 8, 2, 64) defer func() { for i := range p { p[i] = byte(0) } for i := range name { name[i] = byte(0) } }() if err != nil { return nil, err } return &MP{key: key}, nil } func (mp *MP) PrintPassword(site string, counter int, tempType TemplateType) { mp.Lock() defer mp.Unlock() salt := []byte(variant) salt = append(salt, i2b(len(site))...) salt = append(salt, []byte(site)...) salt = append(salt, i2b(counter)...) mac := hmac.New(sha256.New, mp.key) mac.Write(salt) seed := mac.Sum(nil) templates := typeMap[tempType] temp := templates[int(seed[0])%len(templates)] for i, c := range temp { chars := charMap[c] print(string(chars[int(seed[i+1])%len(chars)])) } print("\n") } func (mp *MP) DestroyKey() { mp.Lock() for i := range mp.key { mp.key[i] = byte(0) } mp.key = nil runtime.GC() mp.Unlock() }