// Copyright 2014 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library 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. // // The go-ethereum library 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . 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 = 3 ) 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 { Address string `json:"address"` PrivateKey string `json:"privatekey"` Id string `json:"id"` Version int `json:"version"` } type encryptedKeyJSONV3 struct { Address string `json:"address"` Crypto cryptoJSON Id string `json:"id"` Version int `json:"version"` } type encryptedKeyJSONV1 struct { Address string `json:"address"` Crypto cryptoJSON Id string `json:"id"` Version string `json:"version"` } type cryptoJSON struct { Cipher string `json:"cipher"` CipherText string `json:"ciphertext"` CipherParams cipherparamsJSON `json:"cipherparams"` KDF string `json:"kdf"` KDFParams map[string]interface{} `json:"kdfparams"` MAC string `json:"mac"` } type cipherparamsJSON struct { IV string `json:"iv"` } type scryptParamsJSON struct { N int `json:"n"` R int `json:"r"` P int `json:"p"` DkLen int `json:"dklen"` Salt string `json:"salt"` } func (k *Key) MarshalJSON() (j []byte, err error) { jStruct := plainKeyJSON{ hex.EncodeToString(k.Address[:]), hex.EncodeToString(FromECDSA(k.PrivateKey)), k.Id.String(), version, } 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: 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) }