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
This commit is contained in:
		@@ -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,14 +102,24 @@ 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
	id := uuid.NewRandom()
 | 
			
		||||
	key := &Key{
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user