CryptoPP::ECP CryptoECDSA::Get_secp256k1_ECP(void) { static bool firstRun = true; static CryptoPP::Integer intN; static CryptoPP::Integer inta; static CryptoPP::Integer intb; static BinaryData N; static BinaryData a; static BinaryData b; if(firstRun) { firstRun = false; N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); a = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000000"); b = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000007"); intN.Decode( N.getPtr(), N.getSize(), UNSIGNED); inta.Decode( a.getPtr(), a.getSize(), UNSIGNED); intb.Decode( b.getPtr(), b.getSize(), UNSIGNED); } return CryptoPP::ECP(intN, inta, intb); }
BinaryData CryptoECDSA::ECAddPoints(BinaryData const & Ax, BinaryData const & Ay, BinaryData const & Bx, BinaryData const & By) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intAx, intAy, intBx, intBy, intCx, intCy; intAx.Decode(Ax.getPtr(), Ax.getSize(), UNSIGNED); intAy.Decode(Ay.getPtr(), Ay.getSize(), UNSIGNED); intBx.Decode(Bx.getPtr(), Bx.getSize(), UNSIGNED); intBy.Decode(By.getPtr(), By.getSize(), UNSIGNED); BTC_ECPOINT A(intAx, intAy); BTC_ECPOINT B(intBx, intBy); BTC_ECPOINT C = ecp.Add(A,B); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
///////////////////////////////////////////////////////////////////////////// // Deterministically generate new public key using a chaincode SecureBinaryData CryptoECDSA::ComputeChainedPublicKey( SecureBinaryData const & binPubKey, SecureBinaryData const & chainCode, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPUBLICKey:" << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; } static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); // Added extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Parse the chaincode as a big-endian integer CryptoPP::Integer mult; mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // "new" init as "old", to make sure it's initialized on the correct curve BTC_PUBKEY oldPubKey = ParsePublicKey(binPubKey); BTC_PUBKEY newPubKey = ParsePublicKey(binPubKey); // Let Crypto++ do the EC math for us, serialize the new public key newPubKey.SetPublicElement( oldPubKey.ExponentiatePublicElement(mult) ); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained public key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return CryptoECDSA::SerializePublicKey(newPubKey); }
void TxOut::unserialize( BinaryData const & str, uint32_t nbytes, TxRef parent, uint32_t idx) { unserialize_checked(str.getPtr(), str.getSize(), nbytes, parent, idx); }
BinaryData CryptoECDSA::ECMultiplyScalars(BinaryData const & A, BinaryData const & B) { // Hardcode the order of the secp256k1 EC group static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer intA, intB, intC, intN; intA.Decode(A.getPtr(), A.getSize(), UNSIGNED); intB.Decode(B.getPtr(), B.getSize(), UNSIGNED); intN.Decode(N.getPtr(), N.getSize(), UNSIGNED); intC = a_times_b_mod_c(intA, intB, intN); BinaryData C(32); intC.Encode(C.getPtr(), 32, UNSIGNED); return C; }
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); }
BinaryData CryptoECDSA::ECInverse(BinaryData const & Ax, BinaryData const & Ay) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intAx, intAy, intCx, intCy; intAx.Decode(Ax.getPtr(), Ax.getSize(), UNSIGNED); intAy.Decode(Ay.getPtr(), Ay.getSize(), UNSIGNED); BTC_ECPOINT A(intAx, intAy); BTC_ECPOINT C = ecp.Inverse(A); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
BinaryData CryptoECDSA::ECMultiplyPoint(BinaryData const & A, BinaryData const & Bx, BinaryData const & By) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intA, intBx, intBy, intCx, intCy; intA.Decode( A.getPtr(), A.getSize(), UNSIGNED); intBx.Decode(Bx.getPtr(), Bx.getSize(), UNSIGNED); intBy.Decode(By.getPtr(), By.getSize(), UNSIGNED); BTC_ECPOINT B(intBx, intBy); BTC_ECPOINT C = ecp.ScalarMultiply(B, intA); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
void ZeroConfContainer::updateZCinDB(const vector<BinaryData>& keysToWrite, const vector<BinaryData>& keysToDelete) { //should run in its own thread to make sure we can get a write tx DB_SELECT dbs = BLKDATA; if (db_->getDbType() != ARMORY_DB_SUPER) dbs = HISTORY; LMDBEnv::Transaction tx; db_->beginDBTransaction(&tx, dbs, LMDB::ReadWrite); for (auto& key : keysToWrite) { StoredTx zcTx; zcTx.createFromTx(txMap_[key], true, true); db_->putStoredZC(zcTx, key); } for (auto& key : keysToDelete) { BinaryData keyWithPrefix; if (key.getSize() == 6) { keyWithPrefix.resize(7); uint8_t* keyptr = keyWithPrefix.getPtr(); keyptr[0] = DB_PREFIX_ZCDATA; memcpy(keyptr + 1, key.getPtr(), 6); } else keyWithPrefix = key; LDBIter dbIter(db_->getIterator(dbs)); if (!dbIter.seekTo(keyWithPrefix)) continue; vector<BinaryData> ktd; do { BinaryDataRef thisKey = dbIter.getKeyRef(); if (!thisKey.startsWith(keyWithPrefix)) break; ktd.push_back(thisKey); } while (dbIter.advanceAndRead(DB_PREFIX_ZCDATA)); for (auto Key : ktd) db_->deleteValue(dbs, Key); } }
BinaryData DBUtils::getMissingHashesKey(uint32_t id) { BinaryData bd; bd.resize(4); id &= 0x00FFFFFF; //24bit ids top id |= DB_PREFIX_MISSING_HASHES << 24; auto keyPtr = (uint32_t*)bd.getPtr(); *keyPtr = id; return bd; }
SecureBinaryData CryptoECDSA::InvMod(const SecureBinaryData& m) { static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer cppM; CryptoPP::Integer cppModulo; cppM.Decode(m.getPtr(), m.getSize(), UNSIGNED); cppModulo.Decode(N.getPtr(), N.getSize(), UNSIGNED); CryptoPP::Integer cppResult = cppM.InverseMod(cppModulo); SecureBinaryData result(32); cppResult.Encode(result.getPtr(), result.getSize(), UNSIGNED); return result; }
vector<BinaryDataRef> SigHashData::tokenize( const BinaryData& data, uint8_t token) { vector<BinaryDataRef> tokens; BinaryRefReader brr(data.getRef()); size_t start = 0; StackInterpreter ss; while (brr.getSizeRemaining()) { auto offset = ss.seekToOpCode(brr, (OPCODETYPE)token); auto len = offset - start; BinaryDataRef bdr(data.getPtr() + start, len); tokens.push_back(move(bdr)); start = brr.getPosition(); } return tokens; }
void OutPoint::unserialize(BinaryData const & bd) { unserialize(bd.getPtr(), bd.getSize()); }
void TxOutRef::unserialize(BinaryData const & str, uint32_t nbytes, TxRef* parent, int32_t idx) { unserialize(str.getPtr(), nbytes, parent, idx); }
///////////////////////////////////////////////////////////////////////////// // Deterministically generate new private key using a chaincode // Changed: added using the hash of the public key to the mix // b/c multiplying by the chaincode alone is too "linear" // (there's no reason to believe it's insecure, but it doesn't // hurt to add some extra entropy/non-linearity to the chain // generation process) SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey( SecureBinaryData const & binPrivKey, SecureBinaryData const & chainCode, SecureBinaryData binPubKey, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPrivateKey:" << endl; cout << " BinPrv: " << binPrivKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; } if( binPubKey.getSize()==0 ) binPubKey = ComputePublicKey(binPrivKey); if( binPrivKey.getSize() != 32 || chainCode.getSize() != 32) { LOGERR << "***ERROR: Invalid private key or chaincode (both must be 32B)"; LOGERR << "BinPrivKey: " << binPrivKey.getSize(); LOGERR << "BinPrivKey: (not logged for security)"; //LOGERR << "BinPrivKey: " << binPrivKey.toHexStr(); LOGERR << "BinChain : " << chainCode.getSize(); LOGERR << "BinChain : " << chainCode.toHexStr(); } // Adding extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Hard-code the order of the group static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData().CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer mult, origPrivExp, ecOrder; // A mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // B origPrivExp.Decode(binPrivKey.getPtr(), binPrivKey.getSize(), UNSIGNED); // C ecOrder.Decode(SECP256K1_ORDER_BE.getPtr(), SECP256K1_ORDER_BE.getSize(), UNSIGNED); // A*B mod C will get us a new private key exponent CryptoPP::Integer newPrivExponent = a_times_b_mod_c(mult, origPrivExp, ecOrder); // Convert new private exponent to big-endian binary string SecureBinaryData newPrivData(32); newPrivExponent.Encode(newPrivData.getPtr(), newPrivData.getSize(), UNSIGNED); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained private key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return newPrivData; }