| 
									
										
										
										
											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" | 
					
						
							|  |  |  | 	"code.google.com/p/go-uuid/uuid" | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							|  |  |  | 	"crypto/elliptic" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 	Address []byte | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 	Id         []byte | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 	Address    []byte | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	PrivateKey []byte | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | type cipherJSON struct { | 
					
						
							|  |  |  | 	Salt       []byte | 
					
						
							|  |  |  | 	IV         []byte | 
					
						
							|  |  |  | 	CipherText []byte | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | type encryptedKeyJSON struct { | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 	Id      []byte | 
					
						
							|  |  |  | 	Address []byte | 
					
						
							|  |  |  | 	Crypto  cipherJSON | 
					
						
							| 
									
										
										
										
											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-01-25 02:07:20 +01:00
										 |  |  | 		k.Id, | 
					
						
							|  |  |  | 		k.Address, | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 		FromECDSA(k.PrivateKey), | 
					
						
							| 
									
										
										
										
											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-01-15 17:45:45 +01:00
										 |  |  | 	*u = keyJSON.Id | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 	k.Id = *u | 
					
						
							|  |  |  | 	k.Address = keyJSON.Address | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | 	k.PrivateKey = ToECDSA(keyJSON.PrivateKey) | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-07 16:06:26 +01:00
										 |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-15 17:45:45 +01:00
										 |  |  | func NewKey(rand io.Reader) *Key { | 
					
						
							|  |  |  | 	randBytes := make([]byte, 32) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 	_, x, y, err := elliptic.GenerateKey(S256(), reader) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic("key generation: elliptic.GenerateKey failed: " + err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	privateKeyMarshalled := elliptic.Marshal(S256(), x, y) | 
					
						
							|  |  |  | 	privateKeyECDSA := ToECDSA(privateKeyMarshalled) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id := uuid.NewRandom() | 
					
						
							| 
									
										
										
										
											2015-01-20 23:55:13 +01:00
										 |  |  | 	key := &Key{ | 
					
						
							| 
									
										
										
										
											2015-01-25 02:07:20 +01:00
										 |  |  | 		Id:         id, | 
					
						
							| 
									
										
										
										
											2015-01-28 05:12:57 +01:00
										 |  |  | 		Address:    PubkeyToAddress(privateKeyECDSA.PublicKey), | 
					
						
							| 
									
										
										
										
											2015-01-20 23:55:13 +01:00
										 |  |  | 		PrivateKey: privateKeyECDSA, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-31 15:39:33 +01:00
										 |  |  | 	return key | 
					
						
							|  |  |  | } |