mirror of https://github.com/status-im/op-geth.git
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
This commit is contained in:
parent
ac3371bcb6
commit
29a5a92d13
|
@ -48,19 +48,34 @@ type plainKeyJSON struct {
|
|||
PrivateKey []byte
|
||||
}
|
||||
|
||||
type cipherJSON struct {
|
||||
MAC []byte
|
||||
Salt []byte
|
||||
IV []byte
|
||||
CipherText []byte
|
||||
}
|
||||
|
||||
type encryptedKeyJSON struct {
|
||||
Id []byte
|
||||
Address []byte
|
||||
Crypto cipherJSON
|
||||
}
|
||||
|
||||
type cipherJSON struct {
|
||||
MAC []byte
|
||||
Salt []byte
|
||||
IV []byte
|
||||
KeyHeader keyHeaderJSON
|
||||
CipherText []byte
|
||||
}
|
||||
|
||||
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) {
|
||||
jStruct := plainKeyJSON{
|
||||
k.Id,
|
||||
|
|
|
@ -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
|
||||
|
||||
authArray := []byte(auth)
|
||||
derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen)
|
||||
// used in MAC
|
||||
keyHeaderJSONStr, err := json.Marshal(keyHeader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
calculatedMAC := Sha3(derivedKey[16:32], cipherText)
|
||||
// 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, n, r, p, dkLen)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
calculatedMAC := Sha3(keyHeaderJSONStr, derivedKey[16:32], cipherText)
|
||||
if !bytes.Equal(calculatedMAC, mac) {
|
||||
err = errors.New("Decryption failed: MAC mismatch")
|
||||
return nil, nil, err
|
||||
|
|
Loading…
Reference in New Issue