block index checking on load, extra redundant checks, misc refactoring
[novacoin.git] / key.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto\r
2 // Distributed under the MIT/X11 software license, see the accompanying\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4 \r
5 \r
6 // secp160k1\r
7 // const unsigned int PRIVATE_KEY_SIZE = 192;\r
8 // const unsigned int PUBLIC_KEY_SIZE  = 41;\r
9 // const unsigned int SIGNATURE_SIZE   = 48;\r
10 //\r
11 // secp192k1\r
12 // const unsigned int PRIVATE_KEY_SIZE = 222;\r
13 // const unsigned int PUBLIC_KEY_SIZE  = 49;\r
14 // const unsigned int SIGNATURE_SIZE   = 57;\r
15 //\r
16 // secp224k1\r
17 // const unsigned int PRIVATE_KEY_SIZE = 250;\r
18 // const unsigned int PUBLIC_KEY_SIZE  = 57;\r
19 // const unsigned int SIGNATURE_SIZE   = 66;\r
20 //\r
21 // secp256k1:\r
22 // const unsigned int PRIVATE_KEY_SIZE = 279;\r
23 // const unsigned int PUBLIC_KEY_SIZE  = 65;\r
24 // const unsigned int SIGNATURE_SIZE   = 72;\r
25 //\r
26 // see www.keylength.com\r
27 // script supports up to 75 for single byte push\r
28 \r
29 \r
30 \r
31 class key_error : public std::runtime_error\r
32 {\r
33 public:\r
34     explicit key_error(const std::string& str) : std::runtime_error(str) {}\r
35 };\r
36 \r
37 \r
38 // secure_allocator is defined in serialize.h\r
39 typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;\r
40 \r
41 \r
42 \r
43 class CKey\r
44 {\r
45 protected:\r
46     EC_KEY* pkey;\r
47     bool fSet;\r
48 \r
49 public:\r
50     CKey()\r
51     {\r
52         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);\r
53         if (pkey == NULL)\r
54             throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");\r
55         fSet = false;\r
56     }\r
57 \r
58     CKey(const CKey& b)\r
59     {\r
60         pkey = EC_KEY_dup(b.pkey);\r
61         if (pkey == NULL)\r
62             throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");\r
63         fSet = b.fSet;\r
64     }\r
65 \r
66     CKey& operator=(const CKey& b)\r
67     {\r
68         if (!EC_KEY_copy(pkey, b.pkey))\r
69             throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");\r
70         fSet = b.fSet;\r
71         return (*this);\r
72     }\r
73 \r
74     ~CKey()\r
75     {\r
76         EC_KEY_free(pkey);\r
77     }\r
78 \r
79     bool IsNull() const\r
80     {\r
81         return !fSet;\r
82     }\r
83 \r
84     void MakeNewKey()\r
85     {\r
86         if (!EC_KEY_generate_key(pkey))\r
87             throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");\r
88         fSet = true;\r
89     }\r
90 \r
91     bool SetPrivKey(const CPrivKey& vchPrivKey)\r
92     {\r
93         const unsigned char* pbegin = &vchPrivKey[0];\r
94         if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))\r
95             return false;\r
96         fSet = true;\r
97         return true;\r
98     }\r
99 \r
100     CPrivKey GetPrivKey() const\r
101     {\r
102         unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);\r
103         if (!nSize)\r
104             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");\r
105         CPrivKey vchPrivKey(nSize, 0);\r
106         unsigned char* pbegin = &vchPrivKey[0];\r
107         if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)\r
108             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");\r
109         return vchPrivKey;\r
110     }\r
111 \r
112     bool SetPubKey(const vector<unsigned char>& vchPubKey)\r
113     {\r
114         const unsigned char* pbegin = &vchPubKey[0];\r
115         if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))\r
116             return false;\r
117         fSet = true;\r
118         return true;\r
119     }\r
120 \r
121     vector<unsigned char> GetPubKey() const\r
122     {\r
123         unsigned int nSize = i2o_ECPublicKey(pkey, NULL);\r
124         if (!nSize)\r
125             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");\r
126         vector<unsigned char> vchPubKey(nSize, 0);\r
127         unsigned char* pbegin = &vchPubKey[0];\r
128         if (i2o_ECPublicKey(pkey, &pbegin) != nSize)\r
129             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");\r
130         return vchPubKey;\r
131     }\r
132 \r
133     bool Sign(uint256 hash, vector<unsigned char>& vchSig)\r
134     {\r
135         vchSig.clear();\r
136         unsigned char pchSig[10000];\r
137         unsigned int nSize = 0;\r
138         if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))\r
139             return false;\r
140         vchSig.resize(nSize);\r
141         memcpy(&vchSig[0], pchSig, nSize);\r
142         return true;\r
143     }\r
144 \r
145     bool Verify(uint256 hash, const vector<unsigned char>& vchSig)\r
146     {\r
147         // -1 = error, 0 = bad sig, 1 = good\r
148         if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)\r
149             return false;\r
150         return true;\r
151     }\r
152 \r
153     static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector<unsigned char>& vchSig)\r
154     {\r
155         CKey key;\r
156         if (!key.SetPrivKey(vchPrivKey))\r
157             return false;\r
158         return key.Sign(hash, vchSig);\r
159     }\r
160 \r
161     static bool Verify(const vector<unsigned char>& vchPubKey, uint256 hash, const vector<unsigned char>& vchSig)\r
162     {\r
163         CKey key;\r
164         if (!key.SetPubKey(vchPubKey))\r
165             return false;\r
166         return key.Verify(hash, vchSig);\r
167     }\r
168 };\r