| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | /* | 
					
						
							|  |  |  | 	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 <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @authors | 
					
						
							|  |  |  |  * 	Gustav Simonsson <gustav.simonsson@gmail.com> | 
					
						
							|  |  |  |  * @date 2015 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package crypto | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | 	"encoding/hex" | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2015-02-10 12:29:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"code.google.com/p/go-uuid/uuid" | 
					
						
							| 
									
										
										
										
											2015-04-02 21:14:25 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	version = "1" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | type Key struct { | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 	Id uuid.UUID // Version 4 "random" for unique id not derived from key data | 
					
						
							|  |  |  | 	// to simplify lookups we also store the address | 
					
						
							| 
									
										
										
										
											2015-04-02 21:14:25 +02:00
										 |  |  | 	Address common.Address | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	// we only store privkey as pubkey/address can be derived from it | 
					
						
							|  |  |  | 	// privkey in this struct is always in plaintext | 
					
						
							|  |  |  | 	PrivateKey *ecdsa.PrivateKey | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | type plainKeyJSON struct { | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | 	Address    string `json:"address"` | 
					
						
							|  |  |  | 	PrivateKey string `json:"privatekey"` | 
					
						
							|  |  |  | 	Id         string `json:"id"` | 
					
						
							|  |  |  | 	Version    string `json:"version"` | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 13:24:12 +02:00
										 |  |  | type encryptedKeyJSON struct { | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | 	Address string `json:"address"` | 
					
						
							|  |  |  | 	Crypto  cryptoJSON | 
					
						
							|  |  |  | 	Id      string `json:"id"` | 
					
						
							|  |  |  | 	Version string `json:"version"` | 
					
						
							| 
									
										
										
										
											2015-04-15 13:24:12 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | type cryptoJSON struct { | 
					
						
							|  |  |  | 	Cipher       string           `json:"cipher"` | 
					
						
							|  |  |  | 	CipherText   string           `json:"ciphertext"` | 
					
						
							|  |  |  | 	CipherParams cipherparamsJSON `json:"cipherparams"` | 
					
						
							|  |  |  | 	KDF          string           `json:"kdf"` | 
					
						
							|  |  |  | 	KDFParams    scryptParamsJSON `json:"kdfparams"` | 
					
						
							|  |  |  | 	MAC          string           `json:"mac"` | 
					
						
							|  |  |  | 	Version      string           `json:"version"` | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | type cipherparamsJSON struct { | 
					
						
							|  |  |  | 	IV string `json:"iv"` | 
					
						
							| 
									
										
										
										
											2015-04-15 13:24:12 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type scryptParamsJSON struct { | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | 	N     int    `json:"n"` | 
					
						
							|  |  |  | 	R     int    `json:"r"` | 
					
						
							|  |  |  | 	P     int    `json:"p"` | 
					
						
							|  |  |  | 	DkLen int    `json:"dklen"` | 
					
						
							|  |  |  | 	Salt  string `json:"salt"` | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (k *Key) MarshalJSON() (j []byte, err error) { | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	jStruct := plainKeyJSON{ | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | 		hex.EncodeToString(k.Address[:]), | 
					
						
							|  |  |  | 		hex.EncodeToString(FromECDSA(k.PrivateKey)), | 
					
						
							| 
									
										
										
										
											2015-05-10 20:30:02 +02:00
										 |  |  | 		k.Id.String(), | 
					
						
							|  |  |  | 		version, | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	j, err = json.Marshal(jStruct) | 
					
						
							| 
									
										
										
										
											2015-01-07 16:06:26 +01:00
										 |  |  | 	return j, err | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (k *Key) UnmarshalJSON(j []byte) (err error) { | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	keyJSON := new(plainKeyJSON) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	err = json.Unmarshal(j, &keyJSON) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-01-07 16:06:26 +01:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u := new(uuid.UUID) | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | 	*u = uuid.Parse(keyJSON.Id) | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 	k.Id = *u | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 17:00:30 +02:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 13:00:06 +00:00
										 |  |  | func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key { | 
					
						
							|  |  |  | 	id := uuid.NewRandom() | 
					
						
							|  |  |  | 	key := &Key{ | 
					
						
							|  |  |  | 		Id:         id, | 
					
						
							| 
									
										
										
										
											2015-06-04 16:52:23 +02:00
										 |  |  | 		Address:    PubkeyToAddress(privateKeyECDSA.PublicKey), | 
					
						
							| 
									
										
										
										
											2015-03-23 13:00:06 +00:00
										 |  |  | 		PrivateKey: privateKeyECDSA, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return key | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | func NewKey(rand io.Reader) *Key { | 
					
						
							| 
									
										
										
										
											2015-03-11 01:10:25 +01:00
										 |  |  | 	randBytes := make([]byte, 64) | 
					
						
							| 
									
										
										
										
											2015-01-19 20:24:30 +01:00
										 |  |  | 	_, err := rand.Read(randBytes) | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic("key generation: could not read from random source: " + err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	reader := bytes.NewReader(randBytes) | 
					
						
							| 
									
										
										
										
											2015-03-11 01:10:25 +01:00
										 |  |  | 	privateKeyECDSA, err := ecdsa.GenerateKey(S256(), reader) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-03-11 01:10:25 +01:00
										 |  |  | 		panic("key generation: ecdsa.GenerateKey failed: " + err.Error()) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 13:00:06 +00:00
										 |  |  | 	return NewKeyFromECDSA(privateKeyECDSA) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } |