initial commit
This commit is contained in:
commit
78673c0967
4 changed files with 200 additions and 0 deletions
24
LICENSE
Normal file
24
LICENSE
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2016, ston1th
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* The names of the authors and/or contributors may not be used to
|
||||||
|
endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL ston1th BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
7
README.md
Normal file
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# gomp - MasterPassword written in Go
|
||||||
|
|
||||||
|
gomp is the golang implementation of the MasterPassword algorithm.
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
* http://masterpasswordapp.com/algorithm.html
|
||||||
|
* https://github.com/Lyndir/MasterPassword
|
||||||
151
gomp.go
Normal file
151
gomp.go
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
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()
|
||||||
|
}
|
||||||
18
gomp_test.go
Normal file
18
gomp_test.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package mp
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test(t *testing.T) {
|
||||||
|
pw := []byte("1")
|
||||||
|
name := []byte("1")
|
||||||
|
mp, _ := NewMP(pw, name)
|
||||||
|
mp.PrintPassword("1", 1, MaximumSecurityPassword)
|
||||||
|
mp.PrintPassword("1", 1, LongPassword)
|
||||||
|
mp.PrintPassword("1", 1, MediumPassword)
|
||||||
|
mp.PrintPassword("1", 1, BasicPassword)
|
||||||
|
mp.PrintPassword("1", 1, ShortPassword)
|
||||||
|
mp.PrintPassword("1", 1, PIN)
|
||||||
|
mp.PrintPassword("1", 1, Name)
|
||||||
|
mp.DestroyKey()
|
||||||
|
mp.PrintPassword("1", 1, Phrase)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue