1 // Copyright (c) 2009-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
10 #include <openssl/bn.h>
11 #include <openssl/ecdsa.h>
12 #include <openssl/obj_mac.h>
19 static const EC_GROUP
* get()
21 static const ecgroup_order wrapper
;
22 return wrapper
.pgroup
;
27 : pgroup(EC_GROUP_new_by_curve_name(NID_secp256k1
))
33 EC_GROUP_free(pgroup
);
40 * Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
41 * recid selects which key is recovered
42 * if check is non-zero, additional checks are performed
44 int ECDSA_SIG_recover_key_GFp(EC_KEY
*eckey
, ECDSA_SIG
*ecsig
, const unsigned char *msg
, int msglen
, int recid
, int check
)
65 const EC_GROUP
*group
= EC_KEY_get0_group(eckey
);
66 if ((ctx
= BN_CTX_new()) == NULL
) { ret
= -1; goto err
; }
68 order
= BN_CTX_get(ctx
);
69 if (!EC_GROUP_get_order(group
, order
, ctx
)) { ret
= -2; goto err
; }
71 if (!BN_copy(x
, order
)) { ret
=-1; goto err
; }
72 if (!BN_mul_word(x
, i
)) { ret
=-1; goto err
; }
73 if (!BN_add(x
, x
, ecsig
->r
)) { ret
=-1; goto err
; }
74 field
= BN_CTX_get(ctx
);
75 if (!EC_GROUP_get_curve_GFp(group
, field
, NULL
, NULL
, ctx
)) { ret
=-2; goto err
; }
76 if (BN_cmp(x
, field
) >= 0) { ret
=0; goto err
; }
77 if ((R
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
78 if (!EC_POINT_set_compressed_coordinates_GFp(group
, R
, x
, recid
% 2, ctx
)) { ret
=0; goto err
; }
81 if ((O
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
82 if (!EC_POINT_mul(group
, O
, NULL
, R
, order
, ctx
)) { ret
=-2; goto err
; }
83 if (!EC_POINT_is_at_infinity(group
, O
)) { ret
= 0; goto err
; }
85 if ((Q
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
86 n
= EC_GROUP_get_degree(group
);
88 if (!BN_bin2bn(msg
, msglen
, e
)) { ret
=-1; goto err
; }
89 if (8*msglen
> n
) BN_rshift(e
, e
, 8-(n
& 7));
90 zero
= BN_CTX_get(ctx
);
91 if (!BN_zero(zero
)) { ret
=-1; goto err
; }
92 if (!BN_mod_sub(e
, zero
, e
, order
, ctx
)) { ret
=-1; goto err
; }
94 if (!BN_mod_inverse(rr
, ecsig
->r
, order
, ctx
)) { ret
=-1; goto err
; }
95 sor
= BN_CTX_get(ctx
);
96 if (!BN_mod_mul(sor
, ecsig
->s
, rr
, order
, ctx
)) { ret
=-1; goto err
; }
97 eor
= BN_CTX_get(ctx
);
98 if (!BN_mod_mul(eor
, e
, rr
, order
, ctx
)) { ret
=-1; goto err
; }
99 if (!EC_POINT_mul(group
, Q
, eor
, R
, sor
, ctx
)) { ret
=-2; goto err
; }
100 if (!EC_KEY_set_public_key(eckey
, Q
)) { ret
=-2; goto err
; }
109 if (R
!= NULL
) EC_POINT_free(R
);
110 if (O
!= NULL
) EC_POINT_free(O
);
111 if (Q
!= NULL
) EC_POINT_free(Q
);
119 assert(pkey
!= NULL
);
120 int result
= EC_KEY_set_group(pkey
, ecgroup_order::get());
128 void CECKey::GetPubKey(std::vector
<unsigned char> &pubkey
, bool fCompressed
) {
129 EC_KEY_set_conv_form(pkey
, fCompressed
? POINT_CONVERSION_COMPRESSED
: POINT_CONVERSION_UNCOMPRESSED
);
130 int nSize
= i2o_ECPublicKey(pkey
, NULL
);
134 pubkey
.resize(nSize
);
135 unsigned char *pbegin(begin_ptr(pubkey
));
136 int nSize2
= i2o_ECPublicKey(pkey
, &pbegin
);
137 assert(nSize
== nSize2
);
140 bool CECKey::SetPubKey(const unsigned char* pubkey
, size_t size
) {
141 return o2i_ECPublicKey(&pkey
, &pubkey
, size
) != NULL
;
144 bool CECKey::Verify(const uint256
&hash
, const std::vector
<unsigned char>& vchSig
) {
148 // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
149 unsigned char *norm_der
= NULL
;
150 ECDSA_SIG
*norm_sig
= ECDSA_SIG_new();
151 const unsigned char* sigptr
= &vchSig
[0];
153 if (d2i_ECDSA_SIG(&norm_sig
, &sigptr
, vchSig
.size()) == NULL
)
155 /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
156 * error. But OpenSSL's own use of this function redundantly frees the
157 * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
158 * clear contract for the function behaving the same way is more
161 ECDSA_SIG_free(norm_sig
);
164 int derlen
= i2d_ECDSA_SIG(norm_sig
, &norm_der
);
165 ECDSA_SIG_free(norm_sig
);
169 // -1 = error, 0 = bad sig, 1 = good
170 bool ret
= ECDSA_verify(0, (unsigned char*)&hash
, sizeof(hash
), norm_der
, derlen
, pkey
) == 1;
171 OPENSSL_free(norm_der
);
175 bool CECKey::Recover(const uint256
&hash
, const unsigned char *p64
, int rec
)
179 ECDSA_SIG
*sig
= ECDSA_SIG_new();
180 BN_bin2bn(&p64
[0], 32, sig
->r
);
181 BN_bin2bn(&p64
[32], 32, sig
->s
);
182 bool ret
= ECDSA_SIG_recover_key_GFp(pkey
, sig
, (unsigned char*)&hash
, sizeof(hash
), rec
, 0) == 1;
187 bool CECKey::TweakPublic(const unsigned char vchTweak
[32]) {
189 BN_CTX
*ctx
= BN_CTX_new();
191 BIGNUM
*bnTweak
= BN_CTX_get(ctx
);
192 BIGNUM
*bnOrder
= BN_CTX_get(ctx
);
193 BIGNUM
*bnOne
= BN_CTX_get(ctx
);
194 const EC_GROUP
*group
= EC_KEY_get0_group(pkey
);
195 EC_GROUP_get_order(group
, bnOrder
, ctx
); // what a grossly inefficient way to get the (constant) group order...
196 BN_bin2bn(vchTweak
, 32, bnTweak
);
197 if (BN_cmp(bnTweak
, bnOrder
) >= 0)
198 ret
= false; // extremely unlikely
199 EC_POINT
*point
= EC_POINT_dup(EC_KEY_get0_public_key(pkey
), group
);
201 EC_POINT_mul(group
, point
, bnTweak
, point
, bnOne
, ctx
);
202 if (EC_POINT_is_at_infinity(group
, point
))
203 ret
= false; // ridiculously unlikely
204 EC_KEY_set_public_key(pkey
, point
);
205 EC_POINT_free(point
);
211 bool CECKey::SanityCheck()
213 const EC_GROUP
*pgroup
= ecgroup_order::get();
216 // TODO Is there more EC functionality that could be missing?