gomp/gomp.go
2016-04-12 23:03:22 +02:00

151 lines
2.7 KiB
Go

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