/* This file is part of go-ethereum go-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. go-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with go-ethereum. If not, see . */ /** * @authors * Gustav Simonsson * @date 2015 * */ package crypto import ( "bytes" "crypto/ecdsa" "encoding/hex" "encoding/json" "io" "code.google.com/p/go-uuid/uuid" "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 Address common.Address // we only store privkey as pubkey/address can be derived from it // privkey in this struct is always in plaintext PrivateKey *ecdsa.PrivateKey } type plainKeyJSON struct { Version string Id string Address string PrivateKey string } type encryptedKeyJSON struct { Version string Id string Address string Crypto cipherJSON } type cipherJSON struct { MAC string Salt string IV string KeyHeader keyHeaderJSON CipherText string } type keyHeaderJSON struct { Version string Kdf string KdfParams scryptParamsJSON } type scryptParamsJSON struct { N int R int P int DkLen int SaltLen int } func (k *Key) MarshalJSON() (j []byte, err error) { jStruct := plainKeyJSON{ version, k.Id.String(), hex.EncodeToString(k.Address[:]), hex.EncodeToString(FromECDSA(k.PrivateKey)), } j, err = json.Marshal(jStruct) return j, err } func (k *Key) UnmarshalJSON(j []byte) (err error) { keyJSON := new(plainKeyJSON) err = json.Unmarshal(j, &keyJSON) if err != nil { return err } u := new(uuid.UUID) *u = uuid.Parse(keyJSON.Id) k.Id = *u 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{ Id: id, Address: common.BytesToAddress(PubkeyToAddress(privateKeyECDSA.PublicKey)), PrivateKey: privateKeyECDSA, } return key } func NewKey(rand io.Reader) *Key { randBytes := make([]byte, 64) _, err := rand.Read(randBytes) if err != nil { panic("key generation: could not read from random source: " + err.Error()) } reader := bytes.NewReader(randBytes) privateKeyECDSA, err := ecdsa.GenerateKey(S256(), reader) if err != nil { panic("key generation: ecdsa.GenerateKey failed: " + err.Error()) } return NewKeyFromECDSA(privateKeyECDSA) }