From f98e002d9851b8df53a09a0e3189f2e8fdec48df Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Tue, 21 Apr 2015 17:00:30 +0200 Subject: [PATCH] Address pull request comments; key header and hex encoding * Remove key header from unencrypted key file format and replace it with a version field * Change encoding of bytes in key files from base64 to hex --- crypto/key.go | 52 +++++++++++++++++++++++----------- crypto/key_store_passphrase.go | 42 +++++++++++++++++++-------- crypto/key_store_plain.go | 4 +-- 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/crypto/key.go b/crypto/key.go index 067a5a294..1af69d795 100644 --- a/crypto/key.go +++ b/crypto/key.go @@ -26,6 +26,7 @@ package crypto import ( "bytes" "crypto/ecdsa" + "encoding/hex" "encoding/json" "io" @@ -33,6 +34,10 @@ import ( "github.com/ethereum/go-ethereum/common" ) +const ( + version = "1" +) + type Key struct { Id uuid.UUID // Version 4 "random" for unique id not derived from key data // to simplify lookups we also store the address @@ -43,29 +48,31 @@ type Key struct { } type plainKeyJSON struct { - Id []byte - Address []byte - PrivateKey []byte + Version string + Id string + Address string + PrivateKey string } type encryptedKeyJSON struct { - Id []byte - Address []byte + Version string + Id string + Address string Crypto cipherJSON } type cipherJSON struct { - MAC []byte - Salt []byte - IV []byte + MAC string + Salt string + IV string KeyHeader keyHeaderJSON - CipherText []byte + CipherText string } type keyHeaderJSON struct { Version string Kdf string - KdfParams scryptParamsJSON // TODO: make more generic? + KdfParams scryptParamsJSON } type scryptParamsJSON struct { @@ -78,9 +85,10 @@ type scryptParamsJSON struct { func (k *Key) MarshalJSON() (j []byte, err error) { jStruct := plainKeyJSON{ - k.Id, - k.Address.Bytes(), - FromECDSA(k.PrivateKey), + version, + k.Id.String(), + hex.EncodeToString(k.Address[:]), + hex.EncodeToString(FromECDSA(k.PrivateKey)), } j, err = json.Marshal(jStruct) return j, err @@ -94,12 +102,22 @@ func (k *Key) UnmarshalJSON(j []byte) (err error) { } u := new(uuid.UUID) - *u = keyJSON.Id + *u = uuid.Parse(keyJSON.Id) k.Id = *u - k.Address = common.BytesToAddress(keyJSON.Address) - k.PrivateKey = ToECDSA(keyJSON.PrivateKey) + addr, err := hex.DecodeString(keyJSON.Address) + if err != nil { + return err + } - return err + privkey, err := hex.DecodeString(keyJSON.PrivateKey) + if err != nil { + return err + } + + k.Address = common.BytesToAddress(addr) + k.PrivateKey = ToECDSA(privkey) + + return nil } func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key { diff --git a/crypto/key_store_passphrase.go b/crypto/key_store_passphrase.go index 00717b5d1..2e7929cee 100644 --- a/crypto/key_store_passphrase.go +++ b/crypto/key_store_passphrase.go @@ -68,6 +68,7 @@ import ( "bytes" "crypto/aes" "crypto/cipher" + "encoding/hex" "encoding/json" "errors" "io" @@ -164,15 +165,16 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) { mac := Sha3(keyHeaderJSONStr, derivedKey[16:32], cipherText) cipherStruct := cipherJSON{ - mac, - salt, - iv, + hex.EncodeToString(mac), + hex.EncodeToString(salt), + hex.EncodeToString(iv), keyHeaderJSON, - cipherText, + hex.EncodeToString(cipherText), } keyStruct := encryptedKeyJSON{ - key.Id, - key.Address.Bytes(), + version, + key.Id.String(), + hex.EncodeToString(key.Address[:]), cipherStruct, } keyJSON, err := json.Marshal(keyStruct) @@ -190,7 +192,7 @@ func (ks keyStorePassphrase) DeleteKey(keyAddr common.Address, auth string) (err return err } - keyDirPath := filepath.Join(ks.keysDirPath, keyAddr.Hex()) + keyDirPath := filepath.Join(ks.keysDirPath, hex.EncodeToString(keyAddr[:])) return os.RemoveAll(keyDirPath) } @@ -203,12 +205,28 @@ func DecryptKey(ks keyStorePassphrase, keyAddr common.Address, auth string) (key keyProtected := new(encryptedKeyJSON) err = json.Unmarshal(fileContent, keyProtected) - keyId = keyProtected.Id - mac := keyProtected.Crypto.MAC - salt := keyProtected.Crypto.Salt - iv := keyProtected.Crypto.IV + keyId = uuid.Parse(keyProtected.Id) + + mac, err := hex.DecodeString(keyProtected.Crypto.MAC) + if err != nil { + return nil, nil, err + } + + salt, err := hex.DecodeString(keyProtected.Crypto.Salt) + if err != nil { + return nil, nil, err + } + + iv, err := hex.DecodeString(keyProtected.Crypto.IV) + if err != nil { + return nil, nil, err + } + keyHeader := keyProtected.Crypto.KeyHeader - cipherText := keyProtected.Crypto.CipherText + cipherText, err := hex.DecodeString(keyProtected.Crypto.CipherText) + if err != nil { + return nil, nil, err + } // used in MAC keyHeaderJSONStr, err := json.Marshal(keyHeader) diff --git a/crypto/key_store_plain.go b/crypto/key_store_plain.go index 2ade11985..6a8afe27d 100644 --- a/crypto/key_store_plain.go +++ b/crypto/key_store_plain.go @@ -98,12 +98,12 @@ func (ks keyStorePlain) DeleteKey(keyAddr common.Address, auth string) (err erro } func GetKeyFile(keysDirPath string, keyAddr common.Address) (fileContent []byte, err error) { - fileName := keyAddr.Hex() + fileName := hex.EncodeToString(keyAddr[:]) return ioutil.ReadFile(filepath.Join(keysDirPath, fileName, fileName)) } func WriteKeyFile(addr common.Address, keysDirPath string, content []byte) (err error) { - addrHex := addr.Hex() + addrHex := hex.EncodeToString(addr[:]) keyDirPath := filepath.Join(keysDirPath, addrHex) keyFilePath := filepath.Join(keyDirPath, addrHex) err = os.MkdirAll(keyDirPath, 0700) // read, write and dir search for user