Changeset View
Changeset View
Standalone View
Standalone View
src/pubkey.cpp
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Copyright (c) 2017 The Zcash developers | |||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <pubkey.h> | #include <pubkey.h> | ||||
#include <secp256k1.h> | #include <secp256k1.h> | ||||
#include <secp256k1_recovery.h> | #include <secp256k1_recovery.h> | ||||
#include <secp256k1_schnorr.h> | #include <secp256k1_schnorr.h> | ||||
Show All 35 Lines | static int ecdsa_signature_parse_der_lax(const secp256k1_context *ctx, | ||||
/* Sequence length bytes */ | /* Sequence length bytes */ | ||||
if (pos == inputlen) { | if (pos == inputlen) { | ||||
return 0; | return 0; | ||||
} | } | ||||
lenbyte = input[pos++]; | lenbyte = input[pos++]; | ||||
if (lenbyte & 0x80) { | if (lenbyte & 0x80) { | ||||
lenbyte -= 0x80; | lenbyte -= 0x80; | ||||
if (pos + lenbyte > inputlen) { | if (lenbyte > inputlen - pos) { | ||||
return 0; | return 0; | ||||
} | } | ||||
pos += lenbyte; | pos += lenbyte; | ||||
} | } | ||||
/* Integer tag byte for R */ | /* Integer tag byte for R */ | ||||
if (pos == inputlen || input[pos] != 0x02) { | if (pos == inputlen || input[pos] != 0x02) { | ||||
return 0; | return 0; | ||||
} | } | ||||
pos++; | pos++; | ||||
/* Integer length for R */ | /* Integer length for R */ | ||||
if (pos == inputlen) { | if (pos == inputlen) { | ||||
return 0; | return 0; | ||||
} | } | ||||
lenbyte = input[pos++]; | lenbyte = input[pos++]; | ||||
if (lenbyte & 0x80) { | if (lenbyte & 0x80) { | ||||
lenbyte -= 0x80; | lenbyte -= 0x80; | ||||
if (pos + lenbyte > inputlen) { | if (lenbyte > inputlen - pos) { | ||||
return 0; | return 0; | ||||
} | } | ||||
while (lenbyte > 0 && input[pos] == 0) { | while (lenbyte > 0 && input[pos] == 0) { | ||||
pos++; | pos++; | ||||
lenbyte--; | lenbyte--; | ||||
} | } | ||||
if (lenbyte >= sizeof(size_t)) { | static_assert(sizeof(size_t) >= 4, "size_t too small"); | ||||
if (lenbyte >= 4) { | |||||
return 0; | return 0; | ||||
} | } | ||||
rlen = 0; | rlen = 0; | ||||
while (lenbyte > 0) { | while (lenbyte > 0) { | ||||
rlen = (rlen << 8) + input[pos]; | rlen = (rlen << 8) + input[pos]; | ||||
pos++; | pos++; | ||||
lenbyte--; | lenbyte--; | ||||
} | } | ||||
Show All 14 Lines | static int ecdsa_signature_parse_der_lax(const secp256k1_context *ctx, | ||||
/* Integer length for S */ | /* Integer length for S */ | ||||
if (pos == inputlen) { | if (pos == inputlen) { | ||||
return 0; | return 0; | ||||
} | } | ||||
lenbyte = input[pos++]; | lenbyte = input[pos++]; | ||||
if (lenbyte & 0x80) { | if (lenbyte & 0x80) { | ||||
lenbyte -= 0x80; | lenbyte -= 0x80; | ||||
if (pos + lenbyte > inputlen) { | if (lenbyte > inputlen - pos) { | ||||
return 0; | return 0; | ||||
} | } | ||||
while (lenbyte > 0 && input[pos] == 0) { | while (lenbyte > 0 && input[pos] == 0) { | ||||
pos++; | pos++; | ||||
lenbyte--; | lenbyte--; | ||||
} | } | ||||
if (lenbyte >= sizeof(size_t)) { | static_assert(sizeof(size_t) >= 4, "size_t too small"); | ||||
if (lenbyte >= 4) { | |||||
return 0; | return 0; | ||||
} | } | ||||
slen = 0; | slen = 0; | ||||
while (lenbyte > 0) { | while (lenbyte > 0) { | ||||
slen = (slen << 8) + input[pos]; | slen = (slen << 8) + input[pos]; | ||||
pos++; | pos++; | ||||
lenbyte--; | lenbyte--; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | bool CPubKey::VerifySchnorr(const uint256 &hash, | ||||
} | } | ||||
return secp256k1_schnorr_verify(secp256k1_context_verify, &vchSig[0], | return secp256k1_schnorr_verify(secp256k1_context_verify, &vchSig[0], | ||||
hash.begin(), &pubkey); | hash.begin(), &pubkey); | ||||
} | } | ||||
bool CPubKey::RecoverCompact(const uint256 &hash, | bool CPubKey::RecoverCompact(const uint256 &hash, | ||||
const std::vector<uint8_t> &vchSig) { | const std::vector<uint8_t> &vchSig) { | ||||
if (vchSig.size() != 65) { | if (vchSig.size() != COMPACT_SIGNATURE_SIZE) { | ||||
return false; | return false; | ||||
} | } | ||||
int recid = (vchSig[0] - 27) & 3; | int recid = (vchSig[0] - 27) & 3; | ||||
bool fComp = ((vchSig[0] - 27) & 4) != 0; | bool fComp = ((vchSig[0] - 27) & 4) != 0; | ||||
secp256k1_pubkey pubkey; | secp256k1_pubkey pubkey; | ||||
secp256k1_ecdsa_recoverable_signature sig; | secp256k1_ecdsa_recoverable_signature sig; | ||||
if (!secp256k1_ecdsa_recoverable_signature_parse_compact( | if (!secp256k1_ecdsa_recoverable_signature_parse_compact( | ||||
secp256k1_context_verify, &sig, &vchSig[1], recid)) { | secp256k1_context_verify, &sig, &vchSig[1], recid)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, | if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, | ||||
hash.begin())) { | hash.begin())) { | ||||
return false; | return false; | ||||
} | } | ||||
uint8_t pub[65]; | uint8_t pub[PUBLIC_KEY_SIZE]; | ||||
size_t publen = 65; | size_t publen = PUBLIC_KEY_SIZE; | ||||
secp256k1_ec_pubkey_serialize( | secp256k1_ec_pubkey_serialize( | ||||
secp256k1_context_verify, pub, &publen, &pubkey, | secp256k1_context_verify, pub, &publen, &pubkey, | ||||
fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); | fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); | ||||
Set(pub, pub + publen); | Set(pub, pub + publen); | ||||
return true; | return true; | ||||
} | } | ||||
bool CPubKey::IsFullyValid() const { | bool CPubKey::IsFullyValid() const { | ||||
Show All 9 Lines | bool CPubKey::Decompress() { | ||||
if (!IsValid()) { | if (!IsValid()) { | ||||
return false; | return false; | ||||
} | } | ||||
secp256k1_pubkey pubkey; | secp256k1_pubkey pubkey; | ||||
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, | if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, | ||||
&(*this)[0], size())) { | &(*this)[0], size())) { | ||||
return false; | return false; | ||||
} | } | ||||
uint8_t pub[65]; | uint8_t pub[PUBLIC_KEY_SIZE]; | ||||
size_t publen = 65; | size_t publen = PUBLIC_KEY_SIZE; | ||||
secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, | secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, | ||||
&pubkey, SECP256K1_EC_UNCOMPRESSED); | &pubkey, SECP256K1_EC_UNCOMPRESSED); | ||||
Set(pub, pub + publen); | Set(pub, pub + publen); | ||||
return true; | return true; | ||||
} | } | ||||
bool CPubKey::Derive(CPubKey &pubkeyChild, ChainCode &ccChild, | bool CPubKey::Derive(CPubKey &pubkeyChild, ChainCode &ccChild, | ||||
unsigned int nChild, const ChainCode &cc) const { | unsigned int nChild, const ChainCode &cc) const { | ||||
assert(IsValid()); | assert(IsValid()); | ||||
assert((nChild >> 31) == 0); | assert((nChild >> 31) == 0); | ||||
assert(begin() + 33 == end()); | assert(size() == COMPRESSED_PUBLIC_KEY_SIZE); | ||||
uint8_t out[64]; | uint8_t out[64]; | ||||
BIP32Hash(cc, nChild, *begin(), begin() + 1, out); | BIP32Hash(cc, nChild, *begin(), begin() + 1, out); | ||||
memcpy(ccChild.begin(), out + 32, 32); | memcpy(ccChild.begin(), out + 32, 32); | ||||
secp256k1_pubkey pubkey; | secp256k1_pubkey pubkey; | ||||
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, | if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, | ||||
&(*this)[0], size())) { | &(*this)[0], size())) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, | if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, | ||||
out)) { | out)) { | ||||
return false; | return false; | ||||
} | } | ||||
uint8_t pub[33]; | uint8_t pub[COMPRESSED_PUBLIC_KEY_SIZE]; | ||||
size_t publen = 33; | size_t publen = COMPRESSED_PUBLIC_KEY_SIZE; | ||||
secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, | secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, | ||||
&pubkey, SECP256K1_EC_COMPRESSED); | &pubkey, SECP256K1_EC_COMPRESSED); | ||||
pubkeyChild.Set(pub, pub + publen); | pubkeyChild.Set(pub, pub + publen); | ||||
return true; | return true; | ||||
} | } | ||||
void CExtPubKey::Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const { | void CExtPubKey::Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const { | ||||
code[0] = nDepth; | code[0] = nDepth; | ||||
memcpy(code + 1, vchFingerprint, 4); | memcpy(code + 1, vchFingerprint, 4); | ||||
code[5] = (nChild >> 24) & 0xFF; | code[5] = (nChild >> 24) & 0xFF; | ||||
code[6] = (nChild >> 16) & 0xFF; | code[6] = (nChild >> 16) & 0xFF; | ||||
code[7] = (nChild >> 8) & 0xFF; | code[7] = (nChild >> 8) & 0xFF; | ||||
code[8] = (nChild >> 0) & 0xFF; | code[8] = (nChild >> 0) & 0xFF; | ||||
memcpy(code + 9, chaincode.begin(), 32); | memcpy(code + 9, chaincode.begin(), 32); | ||||
assert(pubkey.size() == 33); | assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); | ||||
memcpy(code + 41, pubkey.begin(), 33); | memcpy(code + 41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); | ||||
} | } | ||||
void CExtPubKey::Decode(const uint8_t code[BIP32_EXTKEY_SIZE]) { | void CExtPubKey::Decode(const uint8_t code[BIP32_EXTKEY_SIZE]) { | ||||
nDepth = code[0]; | nDepth = code[0]; | ||||
memcpy(vchFingerprint, code + 1, 4); | memcpy(vchFingerprint, code + 1, 4); | ||||
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | ||||
memcpy(chaincode.begin(), code + 9, 32); | memcpy(chaincode.begin(), code + 9, 32); | ||||
pubkey.Set(code + 41, code + BIP32_EXTKEY_SIZE); | pubkey.Set(code + 41, code + BIP32_EXTKEY_SIZE); | ||||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |