// reconstruct public key from a compact signature // This is only slightly more CPU intensive than just verifying it. // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.size() != 65) return false; int nV = vchSig[0]; if (nV<27 || nV>=35) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { SetCompressedPubKey(); nV -= 4; } if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1) { fSet = true; ECDSA_SIG_free(sig); return true; } ECDSA_SIG_free(sig); return false; }
void CKey::MakeNewKey(bool fCompressed) { if (!EC_KEY_generate_key(pkey)) throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed"); if (fCompressed) SetCompressedPubKey(); fSet = true; }
bool CKey::SetPubKey(const CPubKey& vchPubKey) { const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) return false; fSet = true; if (vchPubKey.vchPubKey.size() == 33) SetCompressedPubKey(); return true; }
bool CCryptKey::SetPubKey(const CPubKey& vchPubKey) { const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) { fSet = true; if (vchPubKey.vchPubKey.size() == 33) SetCompressedPubKey(); return true; } pkey = NULL; Reset(); return false; }
bool CKey::SetSecret(const std::vector<unsigned char>& vch) { EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (pkey == NULL) throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed"); BIGNUM *bn = BN_bin2bn(&vch[0],vch.size(),BN_new()); if (bn == NULL) throw key_error("CKey::SetSecret() : BN_bin2bn failed"); if (!EC_KEY_regenerate_key(pkey,bn)) { BN_clear_free(bn); throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed"); } BN_clear_free(bn); fSet = true; SetCompressedPubKey(); return true; }
bool CKey::SetSecret(const CSecret &vchSecret, bool fCompressed) { EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (pkey == NULL) throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed"); if (vchSecret.size() != 32) throw key_error("CKey::SetSecret() : secret must be 32 bytes"); BIGNUM *bn = BN_bin2bn(&vchSecret[0], 32, BN_new()); if (bn == NULL) throw key_error("CKey::SetSecret() : BN_bin2bn failed"); if (!EC_KEY_regenerate_key(pkey, bn)) { BN_clear_free(bn); throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed"); } BN_clear_free(bn); fSet = true; if (fCompressed || fCompressedPubKey) SetCompressedPubKey(); return true; }
// reconstruct public key from a compact signature // This is only slightly more CPU intensive than just verifying it. // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.size() != 65) return false; int nV = vchSig[0]; if (nV<27 || nV>=35) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); if (!sig) return false; #if OPENSSL_VERSION_NUMBER > 0x1000ffffL // sig_r and sig_s are deallocated by ECDSA_SIG_free(sig); BIGNUM *sig_r = BN_bin2bn(&vchSig[1],32,BN_new()); BIGNUM *sig_s = BN_bin2bn(&vchSig[33],32,BN_new()); if (!sig_r || !sig_s) return false; // copy and transfer ownership to sig ECDSA_SIG_set0(sig, sig_r, sig_s); #else BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); #endif EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { SetCompressedPubKey(); nV -= 4; } if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1) { fSet = true; ECDSA_SIG_free(sig); return true; } ECDSA_SIG_free(sig); return false; }