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