I also did develop my tool, "Colisionador" (collider in spanish), as I do not trust the founds are being sent to the cloud.
I did program it on C, trying to make if super efficient and fast.
I keep the source code closed at the moment, but just ask if you would like to collaborate.
You can run the binaries released it if you want: ...
I can only expressly
warn everyone not to download ready-made binaries from unknown sources and run them on their computer.
I especially don't see a reason for it to be closed source because supposedly everything was done in OpenSSL - even a toddler could do it.
Here's an example of simple OpenSSL one file code that is incredibly fast:
#include <iostream>
#include <vector>
#include <iomanip>
#include <cmath>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <ctime>
#include <sstream>
#include <fstream>
#include <thread>
#include <mutex>
std::string bytesToHex(const std::vector<unsigned char>& bytes) {
std::stringstream ss;
for (unsigned char byte : bytes) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
}
return ss.str();
}
std::vector<unsigned char> calculateSHA256(const std::vector<unsigned char>& data) {
std::vector<unsigned char> hash(SHA256_DIGEST_LENGTH);
SHA256(data.data(), data.size(), hash.data());
return hash;
}
std::vector<unsigned char> calculateRIPEMD160(const std::vector<unsigned char>& data) {
std::vector<unsigned char> hash(RIPEMD160_DIGEST_LENGTH);
RIPEMD160(data.data(), data.size(), hash.data());
return hash;
}
void generateKeys(BIGNUM* minKeyBN, BIGNUM* maxKeyBN, const std::vector<unsigned char>& target_hash160_bytes, std::mutex& outputMutex) {
BIGNUM* range = BN_new();
BIGNUM* randomPrivateKey = BN_new();
// Calculate the range (maxKey - minKey)
BN_sub(range, maxKeyBN, minKeyBN);
EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
const EC_GROUP* curve = EC_KEY_get0_group(ec_key);
EC_GROUP* ec_group = EC_GROUP_dup(curve);
EC_KEY_set_group(ec_key, ec_group);
unsigned char sha256_result[SHA256_DIGEST_LENGTH];
std::vector<unsigned char> ripemd160_result(RIPEMD160_DIGEST_LENGTH);
while (true) {
// Generate a random number in the range [0, range)
BN_rand_range(randomPrivateKey, range);
// Add the minimum value to the generated random number
BN_add(randomPrivateKey, randomPrivateKey, minKeyBN);
// Calculate the number of bytes needed for numBits
int numBits = BN_num_bits(randomPrivateKey);
int numBytes = (numBits + 7) / 8;
std::vector<unsigned char> private_key_bytes(numBytes, 0); // Initialize with zeros
int key_length = BN_bn2bin(randomPrivateKey, private_key_bytes.data());
BIGNUM* bn_private_key = BN_bin2bn(private_key_bytes.data(), key_length, NULL);
EC_KEY_set_private_key(ec_key, bn_private_key);
EC_POINT* public_key_point = EC_POINT_new(ec_group);
EC_POINT_mul(ec_group, public_key_point, bn_private_key, NULL, NULL, NULL);
size_t public_key_length = EC_POINT_point2oct(ec_group, public_key_point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
std::vector<unsigned char> public_key_bytes(public_key_length);
EC_POINT_point2oct(ec_group, public_key_point, POINT_CONVERSION_COMPRESSED, public_key_bytes.data(), public_key_length, NULL);
SHA256(public_key_bytes.data(), public_key_bytes.size(), sha256_result);
ripemd160_result = calculateRIPEMD160(std::vector<unsigned char>(sha256_result, sha256_result + SHA256_DIGEST_LENGTH));
std::string calculated_hash160_hex = bytesToHex(ripemd160_result);
std::string message = "\r\033[01;33m[+] Public Key Hash (Hash 160): " + calculated_hash160_hex;
{
std::lock_guard<std::mutex> lock(outputMutex);
std::cout << message << "\e[?25l";
std::cout.flush();
}
if (ripemd160_result == target_hash160_bytes) {
std::time_t currentTime;
std::time(¤tTime);
std::tm tmStruct = *std::localtime(¤tTime);
std::stringstream timeStringStream;
timeStringStream << std::put_time(&tmStruct, "%Y-%m-%d %H:%M:%S");
std::string formattedTime = timeStringStream.str();
{
std::lock_guard<std::mutex> lock(outputMutex);
std::cout << "\n\033[32m[+] PUZZLE SOLVED: " << formattedTime << "\033[0m" << std::endl;
std::cout << "\r\033[32m[+] Target Public Key Hash (Hash160) found! Private Key: " << bytesToHex(private_key_bytes) << std::endl;
}
std::ofstream file("KEYFOUNDKEYFOUND.txt", std::ios::app);
if (file.is_open()) {
file << "\nPUZZLE SOLVED " << formattedTime;
file << "\nPrivate Key (hex): " << bytesToHex(private_key_bytes);
file << "\n-------------------------------------------------------------------------------------";
file.close();
}
break;
}
EC_POINT_free(public_key_point);
}
BN_free(range);
BN_free(randomPrivateKey);
EC_KEY_free(ec_key);
EC_GROUP_free(ec_group);
}
int main() {
if (OpenSSL_add_all_algorithms() != 1) {
std::cerr << "OpenSSL initialization failed." << std::endl;
return 1;
}
BIGNUM* minKeyBN = BN_new();
BIGNUM* maxKeyBN = BN_new();
// Configuration for the **Puzzle 20**
BN_dec2bn(&minKeyBN, "524287"); // min range
BN_dec2bn(&maxKeyBN, "1048575"); // max range
std::string target_hash160_hex = "b907c3a2a3b27789dfb509b730dd47703c272868";
// Convert the target_hash160_hex string to bytes
std::vector<unsigned char> target_hash160_bytes;
for (size_t i = 0; i < target_hash160_hex.length(); i += 2) {
std::string byteString = target_hash160_hex.substr(i, 2);
unsigned char byte = static_cast<unsigned char>(std::stoul(byteString, nullptr, 16));
target_hash160_bytes.push_back(byte);
}
unsigned int num_cores = std::thread::hardware_concurrency();
const int numThreads = num_cores; // Adjust the number of threads as needed
std::system("clear");
time_t currentTime = std::time(nullptr);
char* minKeyStr = BN_bn2dec(minKeyBN);
char* maxKeyStr = BN_bn2dec(maxKeyBN);
int minKeyBits = BN_num_bits(minKeyBN);
int maxKeyBits = BN_num_bits(maxKeyBN);
int numBits = std::max(minKeyBits, maxKeyBits);
std::cout << "\r\033[01;33m[+] HASH160 Search by NoMachine" << "\n";
std::cout << "\r\033[01;33m[+] " << SSLeay_version(SSLEAY_VERSION) << std::endl;
std::cout << "\r\033[01;33m[+] " << std::ctime(¤tTime);
std::cout << "\r\033[01;33m[+] Puzzle: " << numBits << "\n";
std::cout << "\r\033[01;33m[+] Lower range limit: " << minKeyStr << "\n";
std::cout << "\r\033[01;33m[+] Upper range limit: " << maxKeyStr << "\n";
std::cout << "\r\033[01;33m[+] Using " << num_cores << " CPU cores for parallel search\033[0m" << std::endl;
OPENSSL_free(minKeyStr);
OPENSSL_free(maxKeyStr);
std::cout.flush();
std::mutex outputMutex;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; i++) {
threads.emplace_back(generateKeys, minKeyBN, maxKeyBN, target_hash160_bytes, std::ref(outputMutex));
}
for (std::thread& thread : threads) {
thread.join();
}
// Cleanup
BN_free(minKeyBN);
BN_free(maxKeyBN);
return 0;
}
compile:
g++ -o puzzle puzzle.cpp -lssl -lcrypto -m64 -mssse3 -Wno-write-strings -pthread -O3
./puzzle
- HASH160 Search by NoMachine
- OpenSSL 1.1.1w 11 Sep 2023
- Sat Jun 15 05:54:19 2024
- Puzzle: 20
- Lower range limit: 524287
- Upper range limit: 1048575
- Using 12 CPU cores for parallel search
- Public Key Hash (Hash 160): a1fdc63a27ac54ef78af80d01ce3a55dc3086963
- PUZZLE SOLVED: 2024-06-15 05:54:22
- Target Public Key Hash (Hash160) found! Private Key: 0d2c55
- Public Key Hash (Hash 160): 09bf95da71645a6baf30c9a119fd9b1ac8da7b72
- PUZZLE SOLVED: 2024-06-15 05:54:25
- Target Public Key Hash (Hash160) found! Private Key: 0d2c55
- Public Key Hash (Hash 160): b907c3a2a3b27789dfb509b730dd47703c272868
This will solve everything from Puzzle 1 to Puzzle 40 in a some reasonable period of time. Beyond that, it is impossible by simple brute force. For anything above 40 bits, the BSGS or the Kangaroo algorithm must be used.