First commit
[novacoin.git] / key.h
1 // Copyright (c) 2009 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 is 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 \r
48 public:\r
49     CKey()\r
50     {\r
51         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);\r
52         if (pkey == NULL)\r
53             throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");\r
54     }\r
55 \r
56     CKey(const CKey& b)\r
57     {\r
58         pkey = EC_KEY_dup(b.pkey);\r
59         if (pkey == NULL)\r
60             throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");\r
61     }\r
62 \r
63     CKey& operator=(const CKey& b)\r
64     {\r
65         if (!EC_KEY_copy(pkey, b.pkey))\r
66             throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");\r
67         return (*this);\r
68     }\r
69 \r
70     ~CKey()\r
71     {\r
72         EC_KEY_free(pkey);\r
73     }\r
74 \r
75     void MakeNewKey()\r
76     {\r
77         if (!EC_KEY_generate_key(pkey))\r
78             throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");\r
79     }\r
80 \r
81     bool SetPrivKey(const CPrivKey& vchPrivKey)\r
82     {\r
83         const unsigned char* pbegin = &vchPrivKey[0];\r
84         if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))\r
85             return false;\r
86         return true;\r
87     }\r
88 \r
89     CPrivKey GetPrivKey() const\r
90     {\r
91         unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);\r
92         if (!nSize)\r
93             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");\r
94         CPrivKey vchPrivKey(nSize, 0);\r
95         unsigned char* pbegin = &vchPrivKey[0];\r
96         if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)\r
97             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");\r
98         return vchPrivKey;\r
99     }\r
100 \r
101     bool SetPubKey(const vector<unsigned char>& vchPubKey)\r
102     {\r
103         const unsigned char* pbegin = &vchPubKey[0];\r
104         if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))\r
105             return false;\r
106         return true;\r
107     }\r
108 \r
109     vector<unsigned char> GetPubKey() const\r
110     {\r
111         unsigned int nSize = i2o_ECPublicKey(pkey, NULL);\r
112         if (!nSize)\r
113             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");\r
114         vector<unsigned char> vchPubKey(nSize, 0);\r
115         unsigned char* pbegin = &vchPubKey[0];\r
116         if (i2o_ECPublicKey(pkey, &pbegin) != nSize)\r
117             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");\r
118         return vchPubKey;\r
119     }\r
120 \r
121     bool Sign(uint256 hash, vector<unsigned char>& vchSig)\r
122     {\r
123         vchSig.clear();\r
124         unsigned char pchSig[10000];\r
125         unsigned int nSize = 0;\r
126         if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))\r
127             return false;\r
128         vchSig.resize(nSize);\r
129         memcpy(&vchSig[0], pchSig, nSize);\r
130         return true;\r
131     }\r
132 \r
133     bool Verify(uint256 hash, const vector<unsigned char>& vchSig)\r
134     {\r
135         // -1 = error, 0 = bad sig, 1 = good\r
136         if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)\r
137             return false;\r
138         return true;\r
139     }\r
140 \r
141     static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector<unsigned char>& vchSig)\r
142     {\r
143         CKey key;\r
144         if (!key.SetPrivKey(vchPrivKey))\r
145             return false;\r
146         return key.Sign(hash, vchSig);\r
147     }\r
148 \r
149     static bool Verify(const vector<unsigned char>& vchPubKey, uint256 hash, const vector<unsigned char>& vchSig)\r
150     {\r
151         CKey key;\r
152         if (!key.SetPubKey(vchPubKey))\r
153             return false;\r
154         return key.Verify(hash, vchSig);\r
155     }\r
156 };\r