return ret;
}
+int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
+ while (c1len > c2len) {
+ if (*c1)
+ return 1;
+ c1++;
+ c1len--;
+ }
+ while (c2len > c1len) {
+ if (*c2)
+ return -1;
+ c2++;
+ c2len--;
+ }
+ while (c1len > 0) {
+ if (*c1 > *c2)
+ return 1;
+ if (*c2 > *c1)
+ return -1;
+ c1++;
+ c2++;
+ c1len--;
+ }
+ return 0;
+}
+
+// Order of secp256k1's generator minus 1.
+const unsigned char vchMaxModOrder[32] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
+};
+
+// Half of the order of secp256k1's generator minus 1.
+const unsigned char vchMaxModHalfOrder[32] = {
+ 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
+ 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
+};
+
+const unsigned char *vchZero = NULL;
+
+
+
void CKey::SetCompressedPubKey()
{
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
return fCompressedPubKey;
}
+bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
+ return CompareBigEndian(vch, len, vchZero, 0) > 0 &&
+ CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
+}
+
void CKey::MakeNewKey(bool fCompressed)
{
if (!EC_KEY_generate_key(pkey))
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
+ vchSig.clear();
+ ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
+ if (sig==NULL)
+ return false;
+ const EC_GROUP *group = EC_KEY_get0_group(pkey);
+ CBigNum order, halforder;
+ EC_GROUP_get_order(group, &order, NULL);
+ BN_rshift1(&halforder, &order);
+ // enforce low S values, by negating the value (modulo the order) if above order/2.
+ if (BN_cmp(sig->s, &halforder) > 0) {
+ BN_sub(sig->s, &order, sig->s);
+ }
unsigned int nSize = ECDSA_size(pkey);
vchSig.resize(nSize); // Make sure it is big enough
- if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
- {
+ unsigned char *pos = &vchSig[0];
+ nSize = i2d_ECDSA_SIG(sig, &pos);
+ ECDSA_SIG_free(sig);
+ vchSig.resize(nSize); // Shrink to fit actual size
+ // Testing our new signature
+ if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) {
vchSig.clear();
return false;
}
- vchSig.resize(nSize); // Shrink to fit actual size
return true;
}
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
if (sig==NULL)
return false;
+ const EC_GROUP *group = EC_KEY_get0_group(pkey);
+ CBigNum order, halforder;
+ EC_GROUP_get_order(group, &order, NULL);
+ BN_rshift1(&halforder, &order);
+ // enforce low S values, by negating the value (modulo the order) if above order/2.
+ if (BN_cmp(sig->s, &halforder) > 0) {
+ BN_sub(sig->s, &order, sig->s);
+ }
vchSig.clear();
vchSig.resize(65,0);
int nBitsR = BN_num_bits(sig->r);