bool GenerateAuthCookie(std::string *cookie_out) { const size_t COOKIE_SIZE = 32; unsigned char rand_pwd[COOKIE_SIZE]; GetRandBytes(rand_pwd, COOKIE_SIZE); std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd, rand_pwd+COOKIE_SIZE); /** the umask determines what permissions are used to create this file - * these are set to 077 in init.cpp unless overridden with -sysperms. */ std::ofstream file; fs::path filepath_tmp = GetAuthCookieFile(true); file.open(filepath_tmp.string().c_str()); if (!file.is_open()) { LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath_tmp.string()); return false; } file << cookie; file.close(); fs::path filepath = GetAuthCookieFile(false); if (!RenameOver(filepath_tmp, filepath)) { LogPrintf("Unable to rename cookie authentication file %s to %s\n", filepath_tmp.string(), filepath.string()); return false; } LogPrintf("Generated RPC authentication cookie %s\n", filepath.string()); if (cookie_out) *cookie_out = cookie; return true; }
/** * Returns a string (consisting of 8 random bytes) suitable for use as an * obfuscating XOR key. */ std::vector<unsigned char> CDBWrapper::CreateObfuscateKey() const { unsigned char buff[OBFUSCATE_KEY_NUM_BYTES]; GetRandBytes(buff, OBFUSCATE_KEY_NUM_BYTES); return std::vector<unsigned char>(&buff[0], &buff[OBFUSCATE_KEY_NUM_BYTES]); }
void seed_insecure_rand(bool fDeterministic) { // The seed values have some unlikely fixed points which we avoid. if (fDeterministic) { insecure_rand_Rz = insecure_rand_Rw = 11; } else { uint32_t tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x9068ffffU); insecure_rand_Rz = tmp; do { GetRandBytes((unsigned char*)&tmp, 4); } while (tmp == 0 || tmp == 0x464fffffU); insecure_rand_Rw = tmp; } }
// Send a ping to serialize the connection and ensure we can figure out // when the remote peer thinks it finished sending us data. This reflects // a minor design weakness in BIP 37 as the merkleblock message does not // say how many transactions the remote peer thinks we have: this normally // doesn't matter, but if we have received transactions and then dropped t // hem due to various policies or running out of memory, then we won't be // able to reassemble the block. So we must ask the peer to send the // transactions again. void SendPing(CNode& pfrom) { pfrom.thinBlockNonce = 0; while (pfrom.thinBlockNonce == 0) GetRandBytes((unsigned char*)&pfrom.thinBlockNonce, sizeof(pfrom.thinBlockNonce)); pfrom.PushMessage("ping", pfrom.thinBlockNonce); }
SecureString CMnemonic::Generate(int strength) { if (strength % 32 || strength < 128 || strength > 256) { return SecureString(); } SecureVector data(32); GetRandBytes(&data[0], 32); SecureString mnemonic = FromData(data, strength / 8); return mnemonic; }
uint64_t GetRand(uint64_t nMax) { if (nMax == 0) return 0; // The range of the random source must be a multiple of the modulus // to give every possible output value an equal possibility uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax; uint64_t nRand = 0; do { GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); } while (nRand >= nRange); return (nRand % nMax); }
uint64_t GetRand(uint64_t nMax) { if (nMax == 0) return 0; #ifdef USE_UNSAFE_RANDOM // use this if you want to test with valgrind return random() % nMax; #else // The range of the random source must be a multiple of the modulus // to give every possible output value an equal possibility uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax; uint64_t nRand = 0; do { GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); } while (nRand >= nRange); return (nRand % nMax); #endif }
void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); CSHA512 hasher; unsigned char buf[64]; // First source: OpenSSL's RNG RandAddSeedPerfmon(); GetRandBytes(buf, 32); hasher.Write(buf, 32); // Second source: OS RNG GetOSRand(buf); hasher.Write(buf, 32); // Produce output hasher.Finalize(buf); memcpy(out, buf, num); memory_cleanse(buf, 64); }
bool CBanDB::Write(const banmap_t& banSet) { // Generate random temporary filename unsigned short randv = 0; GetRandBytes((unsigned char*)&randv, sizeof(randv)); std::string tmpfn = strprintf("banlist.dat.%04x", randv); // serialize banlist, checksum data up to that point, then append csum CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); ssBanlist << FLATDATA(Params().MessageStart()); ssBanlist << banSet; uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); ssBanlist << hash; // open temp output file, and associate with CAutoFile boost::filesystem::path pathTmp = GetDataDir() / tmpfn; FILE *file = fopen(pathTmp.string().c_str(), "wb"); CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); if (fileout.IsNull()) return error("%s: Failed to open file %s", __func__, pathTmp.string()); // Write and commit header, data try { fileout << ssBanlist; } catch (const std::exception& e) { return error("%s: Serialize or I/O error - %s", __func__, e.what()); } FileCommit(fileout.Get()); fileout.fclose(); // replace existing banlist.dat, if any, with new banlist.dat.XXXX if (!RenameOver(pathTmp, pathBanlist)) return error("%s: Rename-into-place failed", __func__); return true; }
uint256 GetRandHash() { uint256 hash; GetRandBytes((unsigned char*)&hash, sizeof(hash)); return hash; }
void PaymentServerTests::paymentServerTests() { SelectParams(CBaseChainParams::MAIN); OptionsModel optionsModel; PaymentServer* server = new PaymentServer(nullptr, false); X509_STORE* caStore = X509_STORE_new(); X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64)); PaymentServer::LoadRootCAs(caStore); server->setOptionsModel(&optionsModel); server->uiReady(); std::vector<unsigned char> data; SendCoinsRecipient r; QString merchant; // Now feed PaymentRequests to server, and observe signals it produces // This payment request validates directly against the // caCert1 certificate authority: data = DecodeBase64(paymentrequest1_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("testmerchant.org")); // Signed, but expired, merchant cert in the request: data = DecodeBase64(paymentrequest2_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // 10-long certificate chain, all intermediates valid: data = DecodeBase64(paymentrequest3_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("testmerchant8.org")); // Long certificate chain, with an expired certificate in the middle: data = DecodeBase64(paymentrequest4_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Validly signed, but by a CA not in our root CA list: data = DecodeBase64(paymentrequest5_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Try again with no root CA's, verifiedMerchant should be empty: caStore = X509_STORE_new(); PaymentServer::LoadRootCAs(caStore); data = DecodeBase64(paymentrequest1_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Load second root certificate caStore = X509_STORE_new(); X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64)); PaymentServer::LoadRootCAs(caStore); QByteArray byteArray; // For the tests below we just need the payment request data from // paymentrequestdata.h parsed + stored in r.paymentRequest. // // These tests require us to bypass the following normal client execution flow // shown below to be able to explicitly just trigger a certain condition! // // handleRequest() // -> PaymentServer::eventFilter() // -> PaymentServer::handleURIOrFile() // -> PaymentServer::readPaymentRequestFromFile() // -> PaymentServer::processPaymentRequest() // Contains a testnet paytoaddress, so payment request network doesn't match client network: data = DecodeBase64(paymentrequest1_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized, because network "main" is default, even for // uninitialized payment requests and that will fail our test here. QVERIFY(r.paymentRequest.IsInitialized()); QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false); // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01): data = DecodeBase64(paymentrequest2_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares 1 < GetTime() == false (treated as expired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t): // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t) // -1 is 1969-12-31 23:59:59 (for a 32 bit time values) data = DecodeBase64(paymentrequest3_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false); // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64): // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t) // 0 is 1970-01-01 00:00:00 (for a 32 bit time values) data = DecodeBase64(paymentrequest4_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares -9223372036854775808 < GetTime() == true (treated as expired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); // Test BIP70 DoS protection: unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1]; GetRandBytes(randData, sizeof(randData)); // Write data to a temp file: QTemporaryFile tempFile; tempFile.open(); tempFile.write((const char*)randData, sizeof(randData)); tempFile.close(); // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false QCOMPARE(PaymentServer::verifySize(tempFile.size()), false); // Payment request with amount overflow (amount is set to 21000001 BTC): data = DecodeBase64(paymentrequest5_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo(); for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); } delete server; }
void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply) { if (reply.code == 250) { std::set<std::string> methods; std::string cookiefile; /* * 250-AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE="/home/x/.tor/control_auth_cookie" * 250-AUTH METHODS=NULL * 250-AUTH METHODS=HASHEDPASSWORD */ for (const std::string &s : reply.lines) { std::pair<std::string,std::string> l = SplitTorReplyLine(s); if (l.first == "AUTH") { std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); std::map<std::string,std::string>::iterator i; if ((i = m.find("METHODS")) != m.end()) boost::split(methods, i->second, boost::is_any_of(",")); if ((i = m.find("COOKIEFILE")) != m.end()) cookiefile = i->second; } else if (l.first == "VERSION") { std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); std::map<std::string,std::string>::iterator i; if ((i = m.find("Tor")) != m.end()) { LogPrint("tor", "tor: Connected to Tor version %s\n", i->second); } } } for (const std::string &s : methods) { LogPrint("tor", "tor: Supported authentication method: %s\n", s); } // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD /* Authentication: * cookie: hex-encoded ~/.tor/control_auth_cookie * password: "******" */ std::string torpassword = GetArg("-torpassword", ""); if (!torpassword.empty()) { if (methods.count("HASHEDPASSWORD")) { LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { LogPrint("tor", "tor: Using NULL authentication\n"); conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { // conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0); GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); } else { if (status_cookie.first) { LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); } else { LogPrintf("tor: Authentication cookie %s could not be opened (check permissions)\n", cookiefile); } } } else if (methods.count("HASHEDPASSWORD")) { LogPrintf("tor: The only supported authentication mechanism left is password, but no password provided with -torpassword\n"); } else { LogPrintf("tor: No supported authentication method\n"); } } else { LogPrintf("tor: Requesting protocol info failed\n"); } }
SaltedTxidHasher::SaltedTxidHasher() { GetRandBytes((unsigned char*)&k0, sizeof(k0)); GetRandBytes((unsigned char*)&k1, sizeof(k1)); }