1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
11 #include <openssl/ec.h>
12 #include <openssl/ecdsa.h>
13 #include <openssl/obj_mac.h>
15 #include "allocators.h"
19 // const unsigned int PRIVATE_KEY_SIZE = 192;
20 // const unsigned int PUBLIC_KEY_SIZE = 41;
21 // const unsigned int SIGNATURE_SIZE = 48;
24 // const unsigned int PRIVATE_KEY_SIZE = 222;
25 // const unsigned int PUBLIC_KEY_SIZE = 49;
26 // const unsigned int SIGNATURE_SIZE = 57;
29 // const unsigned int PRIVATE_KEY_SIZE = 250;
30 // const unsigned int PUBLIC_KEY_SIZE = 57;
31 // const unsigned int SIGNATURE_SIZE = 66;
34 // const unsigned int PRIVATE_KEY_SIZE = 279;
35 // const unsigned int PUBLIC_KEY_SIZE = 65;
36 // const unsigned int SIGNATURE_SIZE = 72;
38 // see www.keylength.com
39 // script supports up to 75 for single byte push
41 int extern EC_KEY_regenerate_key(EC_KEY
*eckey
, BIGNUM
*priv_key
);
42 int extern ECDSA_SIG_recover_key_GFp(EC_KEY
*eckey
, ECDSA_SIG
*ecsig
, const unsigned char *msg
, int msglen
, int recid
, int check
);
44 class key_error
: public std::runtime_error
47 explicit key_error(const std::string
& str
) : std::runtime_error(str
) {}
51 // secure_allocator is defined in serialize.h
52 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
53 typedef std::vector
<unsigned char, secure_allocator
<unsigned char> > CPrivKey
;
54 // CSecret is a serialization of just the secret parameter (32 bytes)
55 typedef std::vector
<unsigned char, secure_allocator
<unsigned char> > CSecret
;
57 /** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
63 bool fCompressedPubKey
;
65 void SetCompressedPubKey()
67 EC_KEY_set_conv_form(pkey
, POINT_CONVERSION_COMPRESSED
);
68 fCompressedPubKey
= true;
75 fCompressedPubKey
= false;
76 pkey
= EC_KEY_new_by_curve_name(NID_secp256k1
);
78 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
89 pkey
= EC_KEY_dup(b
.pkey
);
91 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
95 CKey
& operator=(const CKey
& b
)
97 if (!EC_KEY_copy(pkey
, b
.pkey
))
98 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
113 bool IsCompressed() const
115 return fCompressedPubKey
;
118 void MakeNewKey(bool fCompressed
)
120 if (!EC_KEY_generate_key(pkey
))
121 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
123 SetCompressedPubKey();
127 bool SetPrivKey(const CPrivKey
& vchPrivKey
)
129 const unsigned char* pbegin
= &vchPrivKey
[0];
130 if (!d2i_ECPrivateKey(&pkey
, &pbegin
, vchPrivKey
.size()))
136 bool SetSecret(const CSecret
& vchSecret
, bool fCompressed
= false)
139 pkey
= EC_KEY_new_by_curve_name(NID_secp256k1
);
141 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
142 if (vchSecret
.size() != 32)
143 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
144 BIGNUM
*bn
= BN_bin2bn(&vchSecret
[0],32,BN_new());
146 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
147 if (!EC_KEY_regenerate_key(pkey
,bn
))
150 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
154 if (fCompressed
|| fCompressedPubKey
)
155 SetCompressedPubKey();
159 CSecret
GetSecret(bool &fCompressed
) const
163 const BIGNUM
*bn
= EC_KEY_get0_private_key(pkey
);
164 int nBytes
= BN_num_bytes(bn
);
166 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
167 int n
=BN_bn2bin(bn
,&vchRet
[32 - nBytes
]);
169 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
170 fCompressed
= fCompressedPubKey
;
174 CPrivKey
GetPrivKey() const
176 int nSize
= i2d_ECPrivateKey(pkey
, NULL
);
178 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
179 CPrivKey
vchPrivKey(nSize
, 0);
180 unsigned char* pbegin
= &vchPrivKey
[0];
181 if (i2d_ECPrivateKey(pkey
, &pbegin
) != nSize
)
182 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
186 bool SetPubKey(const std::vector
<unsigned char>& vchPubKey
)
188 const unsigned char* pbegin
= &vchPubKey
[0];
189 if (!o2i_ECPublicKey(&pkey
, &pbegin
, vchPubKey
.size()))
192 if (vchPubKey
.size() == 33)
193 SetCompressedPubKey();
197 std::vector
<unsigned char> GetPubKey() const
199 int nSize
= i2o_ECPublicKey(pkey
, NULL
);
201 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
202 std::vector
<unsigned char> vchPubKey(nSize
, 0);
203 unsigned char* pbegin
= &vchPubKey
[0];
204 if (i2o_ECPublicKey(pkey
, &pbegin
) != nSize
)
205 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
209 bool Sign(uint256 hash
, std::vector
<unsigned char>& vchSig
)
211 unsigned int nSize
= ECDSA_size(pkey
);
212 vchSig
.resize(nSize
); // Make sure it is big enough
213 if (!ECDSA_sign(0, (unsigned char*)&hash
, sizeof(hash
), &vchSig
[0], &nSize
, pkey
))
218 vchSig
.resize(nSize
); // Shrink to fit actual size
222 // create a compact signature (65 bytes), which allows reconstructing the used public key
223 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
224 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
225 // 0x1D = second key with even y, 0x1E = second key with odd y
226 bool SignCompact(uint256 hash
, std::vector
<unsigned char>& vchSig
)
229 ECDSA_SIG
*sig
= ECDSA_do_sign((unsigned char*)&hash
, sizeof(hash
), pkey
);
234 int nBitsR
= BN_num_bits(sig
->r
);
235 int nBitsS
= BN_num_bits(sig
->s
);
236 if (nBitsR
<= 256 && nBitsS
<= 256)
239 for (int i
=0; i
<4; i
++)
243 if (fCompressedPubKey
)
244 keyRec
.SetCompressedPubKey();
245 if (ECDSA_SIG_recover_key_GFp(keyRec
.pkey
, sig
, (unsigned char*)&hash
, sizeof(hash
), i
, 1) == 1)
246 if (keyRec
.GetPubKey() == this->GetPubKey())
254 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
256 vchSig
[0] = nRecId
+27+(fCompressedPubKey
? 4 : 0);
257 BN_bn2bin(sig
->r
,&vchSig
[33-(nBitsR
+7)/8]);
258 BN_bn2bin(sig
->s
,&vchSig
[65-(nBitsS
+7)/8]);
265 // reconstruct public key from a compact signature
266 // This is only slightly more CPU intensive than just verifying it.
267 // If this function succeeds, the recovered public key is guaranteed to be valid
268 // (the signature is a valid signature of the given data for that key)
269 bool SetCompactSignature(uint256 hash
, const std::vector
<unsigned char>& vchSig
)
271 if (vchSig
.size() != 65)
276 ECDSA_SIG
*sig
= ECDSA_SIG_new();
277 BN_bin2bn(&vchSig
[1],32,sig
->r
);
278 BN_bin2bn(&vchSig
[33],32,sig
->s
);
281 pkey
= EC_KEY_new_by_curve_name(NID_secp256k1
);
284 SetCompressedPubKey();
287 if (ECDSA_SIG_recover_key_GFp(pkey
, sig
, (unsigned char*)&hash
, sizeof(hash
), nV
- 27, 0) == 1)
296 bool Verify(uint256 hash
, const std::vector
<unsigned char>& vchSig
)
298 // -1 = error, 0 = bad sig, 1 = good
299 if (ECDSA_verify(0, (unsigned char*)&hash
, sizeof(hash
), &vchSig
[0], vchSig
.size(), pkey
) != 1)
304 // Verify a compact signature
305 bool VerifyCompact(uint256 hash
, const std::vector
<unsigned char>& vchSig
)
308 if (!key
.SetCompactSignature(hash
, vchSig
))
310 if (GetPubKey() != key
.GetPubKey())
321 CSecret secret
= GetSecret(fCompr
);
323 key2
.SetSecret(secret
, fCompr
);
324 return GetPubKey() == key2
.GetPubKey();