diff options
author | Gustav Simonsson <gustav.simonsson@gmail.com> | 2015-04-15 19:24:12 +0800 |
---|---|---|
committer | Gustav Simonsson <gustav.simonsson@gmail.com> | 2015-05-12 23:19:39 +0800 |
commit | 29a5a92d13cad45794c6e42cb97260a9ab9900ab (patch) | |
tree | bfd1ce21673be3610f188a639518bd8e331a8d2e | |
parent | ac3371bcb69b090fa9b5a8da96916fa0aa15ed0f (diff) | |
download | dexon-29a5a92d13cad45794c6e42cb97260a9ab9900ab.tar.gz dexon-29a5a92d13cad45794c6e42cb97260a9ab9900ab.tar.zst dexon-29a5a92d13cad45794c6e42cb97260a9ab9900ab.zip |
Add key header to encrypted keys
* Add key header containing key version, kdf and kdf params
* Store key header as JSON in the key file
* Read in KDF params from key header
* Include key header in MAC calculation and MAC verification
-rw-r--r-- | crypto/key.go | 23 | ||||
-rw-r--r-- | crypto/key_store_passphrase.go | 41 |
2 files changed, 57 insertions, 7 deletions
diff --git a/crypto/key.go b/crypto/key.go index 5e1f3637e..067a5a294 100644 --- a/crypto/key.go +++ b/crypto/key.go @@ -48,17 +48,32 @@ type plainKeyJSON struct { PrivateKey []byte } +type encryptedKeyJSON struct { + Id []byte + Address []byte + Crypto cipherJSON +} + type cipherJSON struct { MAC []byte Salt []byte IV []byte + KeyHeader keyHeaderJSON CipherText []byte } -type encryptedKeyJSON struct { - Id []byte - Address []byte - Crypto cipherJSON +type keyHeaderJSON struct { + Version string + Kdf string + KdfParams scryptParamsJSON // TODO: make more generic? +} + +type scryptParamsJSON struct { + N int + R int + P int + DkLen int + SaltLen int } func (k *Key) MarshalJSON() (j []byte, err error) { diff --git a/crypto/key_store_passphrase.go b/crypto/key_store_passphrase.go index 739483d9f..00717b5d1 100644 --- a/crypto/key_store_passphrase.go +++ b/crypto/key_store_passphrase.go @@ -81,6 +81,8 @@ import ( ) const ( + keyHeaderVersion = "1" + keyHeaderKDF = "scrypt" // 2^18 / 8 / 1 uses 256MB memory and approx 1s CPU time on a modern CPU. scryptN = 1 << 18 scryptr = 8 @@ -140,12 +142,32 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { cipherText := make([]byte, len(toEncrypt)) AES128CBCEncrypter.CryptBlocks(cipherText, toEncrypt) - mac := Sha3(derivedKey[16:32], cipherText) + paramsJSON := scryptParamsJSON{ + N: scryptN, + R: scryptr, + P: scryptp, + DkLen: scryptdkLen, + SaltLen: 32, + } + + keyHeaderJSON := keyHeaderJSON{ + Version: keyHeaderVersion, + Kdf: keyHeaderKDF, + KdfParams: paramsJSON, + } + + keyHeaderJSONStr, err := json.Marshal(keyHeaderJSON) + if err != nil { + return err + } + + mac := Sha3(keyHeaderJSONStr, derivedKey[16:32], cipherText) cipherStruct := cipherJSON{ mac, salt, iv, + keyHeaderJSON, cipherText, } keyStruct := encryptedKeyJSON{ @@ -185,15 +207,28 @@ func DecryptKey(ks keyStorePassphrase, keyAddr common.Address, auth string) (key mac := keyProtected.Crypto.MAC salt := keyProtected.Crypto.Salt iv := keyProtected.Crypto.IV + keyHeader := keyProtected.Crypto.KeyHeader cipherText := keyProtected.Crypto.CipherText + // used in MAC + keyHeaderJSONStr, err := json.Marshal(keyHeader) + if err != nil { + return nil, nil, err + } + + // TODO: make this more generic when we support different KDF params / key versions + n := keyHeader.KdfParams.N + r := keyHeader.KdfParams.R + p := keyHeader.KdfParams.P + dkLen := keyHeader.KdfParams.DkLen + authArray := []byte(auth) - derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen) + derivedKey, err := scrypt.Key(authArray, salt, n, r, p, dkLen) if err != nil { return nil, nil, err } - calculatedMAC := Sha3(derivedKey[16:32], cipherText) + calculatedMAC := Sha3(keyHeaderJSONStr, derivedKey[16:32], cipherText) if !bytes.Equal(calculatedMAC, mac) { err = errors.New("Decryption failed: MAC mismatch") return nil, nil, err |