Commit 29a5a92d authored by Gustav Simonsson's avatar Gustav Simonsson

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
parent ac3371bc
...@@ -48,17 +48,32 @@ type plainKeyJSON struct { ...@@ -48,17 +48,32 @@ type plainKeyJSON struct {
PrivateKey []byte PrivateKey []byte
} }
type encryptedKeyJSON struct {
Id []byte
Address []byte
Crypto cipherJSON
}
type cipherJSON struct { type cipherJSON struct {
MAC []byte MAC []byte
Salt []byte Salt []byte
IV []byte IV []byte
KeyHeader keyHeaderJSON
CipherText []byte CipherText []byte
} }
type encryptedKeyJSON struct { type keyHeaderJSON struct {
Id []byte Version string
Address []byte Kdf string
Crypto cipherJSON 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) { func (k *Key) MarshalJSON() (j []byte, err error) {
......
...@@ -81,6 +81,8 @@ import ( ...@@ -81,6 +81,8 @@ import (
) )
const ( const (
keyHeaderVersion = "1"
keyHeaderKDF = "scrypt"
// 2^18 / 8 / 1 uses 256MB memory and approx 1s CPU time on a modern CPU. // 2^18 / 8 / 1 uses 256MB memory and approx 1s CPU time on a modern CPU.
scryptN = 1 << 18 scryptN = 1 << 18
scryptr = 8 scryptr = 8
...@@ -140,12 +142,32 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { ...@@ -140,12 +142,32 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
cipherText := make([]byte, len(toEncrypt)) cipherText := make([]byte, len(toEncrypt))
AES128CBCEncrypter.CryptBlocks(cipherText, 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{ cipherStruct := cipherJSON{
mac, mac,
salt, salt,
iv, iv,
keyHeaderJSON,
cipherText, cipherText,
} }
keyStruct := encryptedKeyJSON{ keyStruct := encryptedKeyJSON{
...@@ -185,15 +207,28 @@ func DecryptKey(ks keyStorePassphrase, keyAddr common.Address, auth string) (key ...@@ -185,15 +207,28 @@ func DecryptKey(ks keyStorePassphrase, keyAddr common.Address, auth string) (key
mac := keyProtected.Crypto.MAC mac := keyProtected.Crypto.MAC
salt := keyProtected.Crypto.Salt salt := keyProtected.Crypto.Salt
iv := keyProtected.Crypto.IV iv := keyProtected.Crypto.IV
keyHeader := keyProtected.Crypto.KeyHeader
cipherText := keyProtected.Crypto.CipherText 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) 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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
calculatedMAC := Sha3(derivedKey[16:32], cipherText) calculatedMAC := Sha3(keyHeaderJSONStr, derivedKey[16:32], cipherText)
if !bytes.Equal(calculatedMAC, mac) { if !bytes.Equal(calculatedMAC, mac) {
err = errors.New("Decryption failed: MAC mismatch") err = errors.New("Decryption failed: MAC mismatch")
return nil, nil, err return nil, nil, err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment