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
|
PrivateKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type cipherJSON struct {
|
|
||||||
MAC []byte
|
|
||||||
Salt []byte
|
|
||||||
IV []byte
|
|
||||||
CipherText []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type encryptedKeyJSON struct {
|
type encryptedKeyJSON struct {
|
||||||
Id []byte
|
Id []byte
|
||||||
Address []byte
|
Address []byte
|
||||||
Crypto cipherJSON
|
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) {
|
func (k *Key) MarshalJSON() (j []byte, err error) {
|
||||||
jStruct := plainKeyJSON{
|
jStruct := plainKeyJSON{
|
||||||
k.Id,
|
k.Id,
|
||||||
|
@ -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) {
|
|||||||
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
|
|||||||
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
|
||||||
|
|
||||||
authArray := []byte(auth)
|
// used in MAC
|
||||||
derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen)
|
keyHeaderJSONStr, err := json.Marshal(keyHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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) {
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user