bool CryptoECDSA::VerifyData(SecureBinaryData const & binMessage, SecureBinaryData const & binSignature, BTC_PUBKEY const & cppPubKey) { CryptoPP::SHA256 sha256; BTC_PRNG prng; assert(cppPubKey.Validate(prng, 3)); // We execute the first SHA256 op, here. Next one is done by Verifier SecureBinaryData hashVal(32); sha256.CalculateDigest(hashVal.getPtr(), binMessage.getPtr(), binMessage.getSize()); // Verifying message BTC_VERIFIER verifier(cppPubKey); return verifier.VerifyMessage((const byte*)hashVal.getPtr(), hashVal.getSize(), (const byte*)binSignature.getPtr(), binSignature.getSize()); }
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey65) { if(CRYPTO_DEBUG) { cout << "BinPub: " << pubKey65.toHexStr() << endl; } // Basically just copying the ParsePublicKey method, but without // the assert that would throw an error from C++ SecureBinaryData pubXbin(pubKey65.getSliceRef( 1,32)); SecureBinaryData pubYbin(pubKey65.getSliceRef(33,32)); CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED); pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created BTC_PUBKEY cppPubKey; cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG static BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
BTC_PUBKEY CryptoECDSA::ComputePublicKey(BTC_PRIVKEY const & cppPrivKey) { BTC_PUBKEY cppPubKey; cppPrivKey.MakePublicKey(cppPubKey); // Validate the public key -- not sure why this needs a prng... BTC_PRNG prng; assert(cppPubKey.Validate(prng, 3)); return cppPubKey; }
bool CryptoECDSA::ECVerifyPoint(BinaryData const & x, BinaryData const & y) { BTC_PUBKEY cppPubKey; CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(x.getPtr(), x.getSize(), UNSIGNED); pubY.Decode(y.getPtr(), y.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
BTC_PUBKEY CryptoECDSA::ParsePublicKey(SecureBinaryData const & pubKeyX32B, SecureBinaryData const & pubKeyY32B) { BTC_PUBKEY cppPubKey; CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubKeyX32B.getPtr(), pubKeyX32B.getSize(), UNSIGNED); pubY.Decode(pubKeyY32B.getPtr(), pubKeyY32B.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; assert(cppPubKey.Validate(prng, 3)); return cppPubKey; }
bool CryptoECDSA::VerifyPublicKeyValid(SecureBinaryData const & pubKey) { if(CRYPTO_DEBUG) { cout << "BinPub: " << pubKey.toHexStr() << endl; } SecureBinaryData keyToCheck(65); // To support compressed keys, we'll just check to see if a key is compressed // and then decompress it. if(pubKey.getSize() == 33) { keyToCheck = UncompressPoint(pubKey); } else { keyToCheck = pubKey; } // Basically just copying the ParsePublicKey method, but without // the assert that would throw an error from C++ SecureBinaryData pubXbin(keyToCheck.getSliceRef( 1,32)); SecureBinaryData pubYbin(keyToCheck.getSliceRef(33,32)); CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(pubXbin.getPtr(), pubXbin.getSize(), UNSIGNED); pubY.Decode(pubYbin.getPtr(), pubYbin.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created BTC_PUBKEY cppPubKey; cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
void StackInterpreter::op_checkmultisig() { //stack needs to have at least m, n, output script if (stack_.size() < 3) throw ScriptException("insufficient stack size for checkmultisig operation"); //pop n auto&& n = pop_back(); auto nI = rawBinaryToInt(n); if (nI < 0 || nI > 20) throw ScriptException("invalid n"); //pop pubkeys map<unsigned, pair<BTC_PUBKEY, BinaryData>> pubkeys; for (unsigned i = 0; i < nI; i++) { auto&& pubkey = pop_back(); CryptoPP::ECP ecp = CryptoECDSA::Get_secp256k1_ECP(); BTC_ECPOINT ptPub; ecp.DecodePoint(ptPub, (byte*)pubkey.getPtr(), pubkey.getSize()); BTC_PUBKEY cppPubKey; cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), ptPub); BTC_PRNG prng; if (cppPubKey.Validate(prng, 3)) { txInEvalState_.pubKeyState_.insert(make_pair(pubkey, false)); auto&& pubkeypair = make_pair(move(cppPubKey), pubkey); pubkeys.insert(move(make_pair(i, move(pubkeypair)))); } } //pop m auto&& m = pop_back(); auto mI = rawBinaryToInt(m); if (mI < 0 || mI > nI) throw ScriptException("invalid m"); txInEvalState_.n_ = nI; txInEvalState_.m_ = mI; //pop sigs struct sigData { BinaryData sig_; SIGHASH_TYPE hashType_; }; vector<sigData> sigVec; while (stack_.size() > 0) { auto&& sig = pop_back(); if (sig.getSize() == 0) break; sigData sdata; sdata.sig_ = sig.getSliceCopy(0, sig.getSize() - 1); //grab hash type sdata.hashType_ = getSigHashSingleByte(*(sig.getPtr() + sig.getSize() - 1)); //push to vector sigVec.push_back(move(sdata)); } //should have at least as many sigs as m /*if (sigVec.size() < mI) throw ScriptException("invalid sig count");*/ //check sigs map<SIGHASH_TYPE, BinaryData> dataToHash; //check sighashdata object if (sigHashDataObject_ == nullptr) sigHashDataObject_ = make_shared<SigHashDataLegacy>(); unsigned validSigCount = 0; int index = nI - 1; auto sigIter = sigVec.rbegin(); while(sigIter != sigVec.rend()) { auto& sigD = *sigIter++; //get data to hash auto& hashdata = dataToHash[sigD.hashType_]; if (hashdata.getSize() == 0) { hashdata = sigHashDataObject_->getDataForSigHash( sigD.hashType_, *txStubPtr_, outputScriptRef_, inputIndex_); } //prepare sig auto&& rs = BtcUtils::extractRSFromDERSig(sigD.sig_); BinaryWriter sigW; //pop pubkeys from deque to verify against sig while (pubkeys.size() > 0) { auto pubkey = pubkeys[index]; pubkeys.erase(index--); #ifdef SIGNER_DEBUG LOGWARN << "Verifying sig for: "; LOGWARN << " pubkey: " << pubkey.second.toHexStr(); auto&& msg_hash = BtcUtils::getHash256(hashdata); LOGWARN << " message: " << hashdata.toHexStr(); #endif if (CryptoECDSA().VerifyData(hashdata, rs, pubkey.first)) { txInEvalState_.pubKeyState_[pubkey.second] = true; validSigCount++; break; } } } if (validSigCount >= mI) op_true(); else op_0(); }