From 069704832aaefc1b861839d93da63a7c7b803750 Mon Sep 17 00:00:00 2001 From: Jarek Kowalski Date: Tue, 27 Sep 2016 22:33:44 -0700 Subject: [PATCH] added SCrypt --- vault/creds.go | 30 +++++++++++++++++++++++------- vault/format.go | 1 + vault/vault.go | 15 +++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/vault/creds.go b/vault/creds.go index 5437fc417..55f873aee 100644 --- a/vault/creds.go +++ b/vault/creds.go @@ -4,32 +4,39 @@ "crypto/sha256" "fmt" + "golang.org/x/crypto/scrypt" + "golang.org/x/crypto/pbkdf2" ) const ( passwordBasedKeySize = 32 - pbkdf2Rounds = 10000 - // MinPasswordLength is the minimum allowed length of a password in charcters. MinPasswordLength = 12 // MinMasterKeyLength is the minimum allowed length of a master key, in bytes. MinMasterKeyLength = 16 + + defaultKeyAlgorithm = "scrypt-65536-8-1" ) +var SupportedKeyAlgorithms = []string{ + "scrypt-65536-8-1", + "pbkdf2-sha256-100000", +} + // Credentials encapsulates credentials used to encrypt a Vault. type Credentials interface { - getMasterKey(salt []byte) []byte + getMasterKey(f *Format) ([]byte, error) } type masterKeyCredentials struct { key []byte } -func (mkc *masterKeyCredentials) getMasterKey(salt []byte) []byte { - return mkc.key +func (mkc *masterKeyCredentials) getMasterKey(f *Format) ([]byte, error) { + return mkc.key, nil } // MasterKey returns master key-based Credentials with the specified key. @@ -45,8 +52,17 @@ type passwordCredentials struct { password string } -func (pc *passwordCredentials) getMasterKey(salt []byte) []byte { - return pbkdf2.Key([]byte(pc.password), salt, pbkdf2Rounds, passwordBasedKeySize, sha256.New) +func (pc *passwordCredentials) getMasterKey(f *Format) ([]byte, error) { + switch f.KeyAlgo { + case "pbkdf2-sha256-100000": + return pbkdf2.Key([]byte(pc.password), f.UniqueID, 100000, passwordBasedKeySize, sha256.New), nil + + case "scrypt-65536-8-1": + return scrypt.Key([]byte(pc.password), f.UniqueID, 65536, 8, 1, passwordBasedKeySize) + + default: + return nil, fmt.Errorf("unsupported key algorithm: %v", f.KeyAlgo) + } } // Password returns password-based Credentials with the specified password. diff --git a/vault/format.go b/vault/format.go index 1b3b6f4c5..ca66760be 100644 --- a/vault/format.go +++ b/vault/format.go @@ -5,6 +5,7 @@ type Format struct { Version string `json:"version"` UniqueID []byte `json:"uniqueID"` + KeyAlgo string `json:"keyAlgo"` Encryption string `json:"encryption"` Checksum string `json:"checksum"` } diff --git a/vault/vault.go b/vault/vault.go index bb9f2740e..b5eaee0f9 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -284,7 +284,15 @@ func Create( if _, err := io.ReadFull(rand.Reader, v.format.UniqueID); err != nil { return nil, err } - v.masterKey = vaultCreds.getMasterKey(v.format.UniqueID) + if v.format.KeyAlgo == "" { + v.format.KeyAlgo = defaultKeyAlgorithm + + } + var err error + v.masterKey, err = vaultCreds.getMasterKey(&v.format) + if err != nil { + return nil, err + } formatBytes, err := json.Marshal(&v.format) if err != nil { @@ -367,7 +375,10 @@ func Open(vaultStorage blob.Storage, vaultCreds Credentials) (*Vault, error) { return nil, err } - v.masterKey = vaultCreds.getMasterKey(v.format.UniqueID) + v.masterKey, err = vaultCreds.getMasterKey(&v.format) + if err != nil { + return nil, err + } v.itemPrefix = prefix cfgData, err := v.decryptBlock(blocks[offset+1])