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