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>
17 * Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
18 * recid selects which key is recovered
19 * if check is non-zero, additional checks are performed
21 int ECDSA_SIG_recover_key_GFp(EC_KEY
*eckey
, ECDSA_SIG
*ecsig
, const unsigned char *msg
, int msglen
, int recid
, int check
)
42 const EC_GROUP
*group
= EC_KEY_get0_group(eckey
);
43 if ((ctx
= BN_CTX_new()) == NULL
) { ret
= -1; goto err
; }
45 order
= BN_CTX_get(ctx
);
46 if (!EC_GROUP_get_order(group
, order
, ctx
)) { ret
= -2; goto err
; }
48 if (!BN_copy(x
, order
)) { ret
=-1; goto err
; }
49 if (!BN_mul_word(x
, i
)) { ret
=-1; goto err
; }
50 if (!BN_add(x
, x
, ecsig
->r
)) { ret
=-1; goto err
; }
51 field
= BN_CTX_get(ctx
);
52 if (!EC_GROUP_get_curve_GFp(group
, field
, NULL
, NULL
, ctx
)) { ret
=-2; goto err
; }
53 if (BN_cmp(x
, field
) >= 0) { ret
=0; goto err
; }
54 if ((R
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
55 if (!EC_POINT_set_compressed_coordinates_GFp(group
, R
, x
, recid
% 2, ctx
)) { ret
=0; goto err
; }
58 if ((O
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
59 if (!EC_POINT_mul(group
, O
, NULL
, R
, order
, ctx
)) { ret
=-2; goto err
; }
60 if (!EC_POINT_is_at_infinity(group
, O
)) { ret
= 0; goto err
; }
62 if ((Q
= EC_POINT_new(group
)) == NULL
) { ret
= -2; goto err
; }
63 n
= EC_GROUP_get_degree(group
);
65 if (!BN_bin2bn(msg
, msglen
, e
)) { ret
=-1; goto err
; }
66 if (8*msglen
> n
) BN_rshift(e
, e
, 8-(n
& 7));
67 zero
= BN_CTX_get(ctx
);
68 if (!BN_zero(zero
)) { ret
=-1; goto err
; }
69 if (!BN_mod_sub(e
, zero
, e
, order
, ctx
)) { ret
=-1; goto err
; }
71 if (!BN_mod_inverse(rr
, ecsig
->r
, order
, ctx
)) { ret
=-1; goto err
; }
72 sor
= BN_CTX_get(ctx
);
73 if (!BN_mod_mul(sor
, ecsig
->s
, rr
, order
, ctx
)) { ret
=-1; goto err
; }
74 eor
= BN_CTX_get(ctx
);
75 if (!BN_mod_mul(eor
, e
, rr
, order
, ctx
)) { ret
=-1; goto err
; }
76 if (!EC_POINT_mul(group
, Q
, eor
, R
, sor
, ctx
)) { ret
=-2; goto err
; }
77 if (!EC_KEY_set_public_key(eckey
, Q
)) { ret
=-2; goto err
; }
86 if (R
!= NULL
) EC_POINT_free(R
);
87 if (O
!= NULL
) EC_POINT_free(O
);
88 if (Q
!= NULL
) EC_POINT_free(Q
);
95 pkey
= EC_KEY_new_by_curve_name(NID_secp256k1
);
103 void CECKey::GetPubKey(std::vector
<unsigned char> &pubkey
, bool fCompressed
) {
104 EC_KEY_set_conv_form(pkey
, fCompressed
? POINT_CONVERSION_COMPRESSED
: POINT_CONVERSION_UNCOMPRESSED
);
105 int nSize
= i2o_ECPublicKey(pkey
, NULL
);
109 pubkey
.resize(nSize
);
110 unsigned char *pbegin(begin_ptr(pubkey
));
111 int nSize2
= i2o_ECPublicKey(pkey
, &pbegin
);
112 assert(nSize
== nSize2
);
115 bool CECKey::SetPubKey(const unsigned char* pubkey
, size_t size
) {
116 return o2i_ECPublicKey(&pkey
, &pubkey
, size
) != NULL
;
119 bool CECKey::Verify(const uint256
&hash
, const std::vector
<unsigned char>& vchSig
) {
123 // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
124 unsigned char *norm_der
= NULL
;
125 ECDSA_SIG
*norm_sig
= ECDSA_SIG_new();
126 const unsigned char* sigptr
= &vchSig
[0];
128 if (d2i_ECDSA_SIG(&norm_sig
, &sigptr
, vchSig
.size()) == NULL
)
130 /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
131 * error. But OpenSSL's own use of this function redundantly frees the
132 * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
133 * clear contract for the function behaving the same way is more
136 ECDSA_SIG_free(norm_sig
);
139 int derlen
= i2d_ECDSA_SIG(norm_sig
, &norm_der
);
140 ECDSA_SIG_free(norm_sig
);
144 // -1 = error, 0 = bad sig, 1 = good
145 bool ret
= ECDSA_verify(0, (unsigned char*)&hash
, sizeof(hash
), norm_der
, derlen
, pkey
) == 1;
146 OPENSSL_free(norm_der
);
150 bool CECKey::Recover(const uint256
&hash
, const unsigned char *p64
, int rec
)
154 ECDSA_SIG
*sig
= ECDSA_SIG_new();
155 BN_bin2bn(&p64
[0], 32, sig
->r
);
156 BN_bin2bn(&p64
[32], 32, sig
->s
);
157 bool ret
= ECDSA_SIG_recover_key_GFp(pkey
, sig
, (unsigned char*)&hash
, sizeof(hash
), rec
, 0) == 1;
162 bool CECKey::TweakPublic(const unsigned char vchTweak
[32]) {
164 BN_CTX
*ctx
= BN_CTX_new();
166 BIGNUM
*bnTweak
= BN_CTX_get(ctx
);
167 BIGNUM
*bnOrder
= BN_CTX_get(ctx
);
168 BIGNUM
*bnOne
= BN_CTX_get(ctx
);
169 const EC_GROUP
*group
= EC_KEY_get0_group(pkey
);
170 EC_GROUP_get_order(group
, bnOrder
, ctx
); // what a grossly inefficient way to get the (constant) group order...
171 BN_bin2bn(vchTweak
, 32, bnTweak
);
172 if (BN_cmp(bnTweak
, bnOrder
) >= 0)
173 ret
= false; // extremely unlikely
174 EC_POINT
*point
= EC_POINT_dup(EC_KEY_get0_public_key(pkey
), group
);
176 EC_POINT_mul(group
, point
, bnTweak
, point
, bnOne
, ctx
);
177 if (EC_POINT_is_at_infinity(group
, point
))
178 ret
= false; // ridiculously unlikely
179 EC_KEY_set_public_key(pkey
, point
);
180 EC_POINT_free(point
);
186 bool CECKey::SanityCheck()
188 EC_KEY
*pkey
= EC_KEY_new_by_curve_name(NID_secp256k1
);
193 // TODO Is there more EC functionality that could be missing?