美食家大橙子 发表于 2025-9-19 01:24:02

Goldenkey教你开发区块链助记词&密钥碰撞/规复器

Goldenkey成品示例
1、弁言

在区块链范畴,私钥和助记词是用户管理和控制数字资产的核心要素。然而,由于各种缘故原由,用户大概会丢失私钥或助记词,导致资产无法访问。本文将从技能角度探究区块链助记词/密钥碰撞/规复器的开发,Goldenkey仅分享实现的大概性和技能路径。
2、基础知识

2.1.私钥与助记词的关系

私钥是区块链中用于天生公钥和地点的关键数据,通常是一个随机天生的256位数字。助记词则是通过BIP39尺度从私钥派生出的一组易于影象的单词序列,用于备份和规复私钥。助记词的天生过程如下:
2.1.1.首天赋生一个随机数(熵),通常为128到256位。

在编程中,天生一个随机数(熵)通常使用加密安全的随机数天生器(CSPRNG)。以下是一些常见编程语言中天生128到256位随机熵的代码示例:
2.1.1.1. Python

在Python中,可以使用  os.urandom  或  secrets.token_hex  来天生随机熵。以下是天生128位和256位熵的代码示例:
import os
import binascii

# 生成128位熵(16字节)
entropy_128 = os.urandom(16)
print("128位熵(十六进制):", binascii.hexlify(entropy_128).decode())

# 生成256位熵(32字节)
entropy_256 = os.urandom(32)
print("256位熵(十六进制):", binascii.hexlify(entropy_256).decode())
大概使用  secrets  模块:
import secrets

# 生成128位熵(16字节)
entropy_128 = secrets.token_bytes(16)
print("128位熵(十六进制):", binascii.hexlify(entropy_128).decode())

# 生成256位熵(32字节)
entropy_256 = secrets.token_bytes(32)
print("256位熵(十六进制):", binascii.hexlify(entropy_256).decode())
2.1.1.2. JavaScript(Node.js)

在Node.js中,可以使用  crypto  模块来天生随机熵:
const crypto = require('crypto');

// 生成128位熵(16字节)
const entropy_128 = crypto.randomBytes(16);
console.log("128位熵(十六进制):", entropy_128.toString('hex'));

// 生成256位熵(32字节)
const entropy_256 = crypto.randomBytes(32);
console.log("256位熵(十六进制):", entropy_256.toString('hex'));
2.1.1.3. C/C++

在C/C++中,可以使用  /dev/urandom  (在Linux体系中)或  CryptGenRandom  (在Windows体系中)来天生随机熵。
Linux 示例(C++)

#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>

std::vector<unsigned char> generateEntropy(int bytes) {
    std::vector<unsigned char> entropy(bytes);
    std::ifstream urandom("/dev/urandom", std::ios::binary);
    urandom.read(reinterpret_cast<char*>(entropy.data()), bytes);
    return entropy;
}

int main() {
    auto entropy_128 = generateEntropy(16);
    std::cout << "128位熵(十六进制): ";
    for (auto byte : entropy_128) {
      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;

    auto entropy_256 = generateEntropy(32);
    std::cout << "256位熵(十六进制): ";
    for (auto byte : entropy_256) {
      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;

    return 0;
}
Windows 示例(C++)

#include <iostream>
#include <iomanip>
#include <vector>
#include <windows.h>
#include <wincrypt.h>

#pragma comment(lib, "Advapi32.lib")

std::vector<unsigned char> generateEntropy(int bytes) {
    std::vector<unsigned char> entropy(bytes);
    HCRYPTPROV hCryptProv;
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
      std::cerr << "CryptAcquireContext failed." << std::endl;
      return {};
    }
    if (!CryptGenRandom(hCryptProv, bytes, entropy.data())) {
      std::cerr << "CryptGenRandom failed." << std::endl;
      CryptReleaseContext(hCryptProv, 0);
      return {};
    }
    CryptReleaseContext(hCryptProv, 0);
    return entropy;
}

int main() {
    auto entropy_128 = generateEntropy(16);
    std::cout << "128位熵(十六进制): ";
    for (auto byte : entropy_128) {
      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;

    auto entropy_256 = generateEntropy(32);
    std::cout << "256位熵(十六进制): ";
    for (auto byte : entropy_256) {
      std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
    }
    std::cout << std::endl;

    return 0;
}
2.1.1.4. Go

在Go语言中,可以使用  crypto/rand  包来天生随机熵:
package main

import (
    "crypto/rand"
    "encoding/hex"
    "fmt"
)

func generateEntropy(bits int) (string, error) {
    bytes := bits / 8
    entropy := make([]byte, bytes)
    _, err := rand.Read(entropy)
    if err != nil {
      return "", err
    }
    return hex.EncodeToString(entropy), nil
}

func main() {
    entropy128, err := generateEntropy(128)
    if err != nil {
      fmt.Println("Error generating 128-bit entropy:", err)
      return
    }
    fmt.Println("128位熵(十六进制):", entropy128)

    entropy256, err := generateEntropy(256)
    if err != nil {
      fmt.Println("Error generating 256-bit entropy:", err)
      return
    }
    fmt.Println("256位熵(十六进制):", entropy256)
}
2.1.1.5. Java

在Java中,可以使用  java.security.SecureRandom  来天生随机熵:
import java.security.SecureRandom;

public class EntropyGenerator {
    public static void main(String[] args) {
      SecureRandom random = new SecureRandom();

      // 生成128位熵(16字节)
      byte[] entropy128 = new byte;
      random.nextBytes(entropy128);
      System.out.println("128位熵(十六进制): " + bytesToHex(entropy128));

      // 生成256位熵(32字节)
      byte[] entropy256 = new byte;
      random.nextBytes(entropy256);
      System.out.println("256位熵(十六进制): " + bytesToHex(entropy256));
    }

    public static String bytesToHex(byte[] bytes) {
      StringBuilder hexString = new StringBuilder();
      for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
      }
      return hexString.toString();
    }
}
这些代码示例展示了怎样在差别编程语言中天生随机熵,并将其转换为十六进制字符串以便于检察。你可以根据须要选择符合的语言和方法来实现。
2.1.2.对熵进行SHA-256哈希计算,截取部分哈希值作为校验位。

在天生助记词的过程中,对熵进行SHA-256哈希计算并截取部分哈希值作为校验位是关键步调之一。以下是用Python代码实现这一过程的示例:
import hashlib
import binascii

def generate_checksum(entropy_bytes):
    """
    对熵进行SHA-256哈希计算,并截取部分哈希值作为校验位。
    校验位的长度取决于熵的长度:
    - 128位熵(16字节):4位校验位
    - 160位熵(20字节):5位校验位
    - 192位熵(24字节):6位校验位
    - 224位熵(28字节):7位校验位
    - 256位熵(32字节):8位校验位
    """
    # 计算SHA-256哈希
    hash_object = hashlib.sha256(entropy_bytes)
    hash_digest = hash_object.digest()

    # 根据熵的长度确定校验位的长度
    entropy_length = len(entropy_bytes) * 8# 转换为比特数
    checksum_length = entropy_length // 32# 校验位长度(比特数)

    # 截取哈希值的前checksum_length位作为校验位
    checksum = bin(int(binascii.hexlify(hash_digest), 16))
    return checksum

# 示例:生成256位熵
entropy_256 = os.urandom(32)# 32字节 = 256位
print("256位熵(十六进制):", binascii.hexlify(entropy_256).decode())

# 生成校验位
checksum = generate_checksum(entropy_256)
print("校验位(二进制):", checksum)
代码剖析:
 
1. 熵的天生:使用  os.urandom(32)  天生256位的熵(32字节)。你可以根据须要天生其他长度的熵,例如128位(16字节)。2. SHA-256哈希计算:使用  hashlib.sha256  对熵进行哈希计算,得到一个256位的哈希值。3. 校验位的天生:根据熵的长度确定校验位的长度。例如:128位熵须要4位校验位。256位熵须要8位校验位。使用  bin(int(binascii.hexlify(hash_digest), 16))  将哈希值转换为二进制字符串。截取哈希值的前  checksum_length  位作为校验位。 输出示例:
假设天生的256位熵为:
256位熵(十六进制): b4f5a7c9f8e6d2b1a3c4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6


校验位大概为:
校验位(二进制): 10101010
扩展到助记词天生
在完整的助记词天生过程中,还须要将熵和校验位组合起来,并将其映射到助记词表中。以下是一个完整的示例,包括天生助记词的过程:
import os
import binascii
import hashlib

# BIP39单词表(简化版,仅展示部分单词)
BIP39_WORDLIST = [
    "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse",
    "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act",
    # ...(完整单词表包含2048个单词)
]

def generate_checksum(entropy_bytes):
    hash_object = hashlib.sha256(entropy_bytes)
    hash_digest = hash_object.digest()
    entropy_length = len(entropy_bytes) * 8
    checksum_length = entropy_length // 32
    checksum = bin(int(binascii.hexlify(hash_digest), 16))
    return checksum

def entropy_to_mnemonic(entropy_bytes):
    # 将熵转换为二进制字符串
    entropy_bin = bin(int(binascii.hexlify(entropy_bytes), 16)).zfill(len(entropy_bytes) * 8)
    # 生成校验位
    checksum = generate_checksum(entropy_bytes)
    # 将熵和校验位组合
    combined = entropy_bin + checksum
    # 每11位映射到一个单词
    mnemonic = []
    for i in range(0, len(combined), 11):
      index = int(combined, 2)
      mnemonic.append(BIP39_WORDLIST)
    return mnemonic

# 示例:生成256位熵
entropy_256 = os.urandom(32)
print("256位熵(十六进制):", binascii.hexlify(entropy_256).decode())

# 生成助记词
mnemonic = entropy_to_mnemonic(entropy_256)
print("助记词:", " ".join(mnemonic))
输出示例:
假设天生的256位熵为:
256位熵(十六进制): b4f5a7c9f8e6d2b1a3c4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6


天生的助记词大概为:
助记词: abandon ability about above absent absorb abstract absurd abuse access

这个代码展示了怎样从熵天生校验位,并将其映射到助记词表中天生助记词。你可以根据须要扩展或修改代码以顺应差别的需求。
2.1.3.将熵和校验位按11位一组映射到2048个单词表中,天生助记词。

将熵和校验位按11位一组映射到2048个单词表中,天生助记词。由于完整的BIP39单词表包含2048个单词,这里我们假设单词表已经加载到程序中(实际开发中可以从文件中读取完整的单词表)。以下是完整的Python代码示例,展示怎样从熵天生助记词:
Python代码示例:
import os
import binascii
import hashlib

# 假设已经加载了完整的BIP39单词表(这里只展示部分单词)
BIP39_WORDLIST = [
    "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse",
    "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act",
    # ...(完整单词表包含2048个单词)
    # 这里省略了完整的单词表,实际开发中可以从文件中加载
]

def generate_checksum(entropy_bytes):
    """
    对熵进行SHA-256哈希计算,并截取部分哈希值作为校验位。
    """
    hash_object = hashlib.sha256(entropy_bytes)
    hash_digest = hash_object.digest()
    entropy_length = len(entropy_bytes) * 8# 转换为比特数
    checksum_length = entropy_length // 32# 校验位长度(比特数)
    checksum = bin(int(binascii.hexlify(hash_digest), 16))# 截取前checksum_length位
    return checksum

def entropy_to_mnemonic(entropy_bytes):
    """
    将熵和校验位按11位一组映射到2048个单词表中,生成助记词。
    """
    # 将熵转换为二进制字符串
    entropy_bin = bin(int(binascii.hexlify(entropy_bytes), 16)).zfill(len(entropy_bytes) * 8)
    # 生成校验位
    checksum = generate_checksum(entropy_bytes)
    # 将熵和校验位组合
    combined = entropy_bin + checksum
    # 每11位映射到一个单词
    mnemonic = []
    for i in range(0, len(combined), 11):
      index = int(combined, 2)# 将11位二进制转换为十进制索引
      mnemonic.append(BIP39_WORDLIST)
    return mnemonic

# 示例:生成256位熵
entropy_256 = os.urandom(32)# 32字节 = 256位
print("256位熵(十六进制):", binascii.hexlify(entropy_256).decode())

# 生成助记词
mnemonic = entropy_to_mnemonic(entropy_256)
print("助记词:", " ".join(mnemonic))
代码剖析:
1. 熵的天生:使用  os.urandom(32)  天生256位的熵(32字节)。2. 校验位的天生:使用  hashlib.sha256  对熵进行哈希计算。根据熵的长度确定校验位的长度。对于256位熵,校验位长度为8位。截取哈希值的前  checksum_length  位作为校验位。3. 熵和校验位的组合:将熵转换为二进制字符串。将校验位附加到熵的二进制字符串末了。4. 映射到助记词表:每11位二进制数映射到一个单词。2048个单词的索引范围是0到2047,恰好可以用11位二进制数表现。使用  int(combined, 2)  将11位二进制数转换为十进制索引。根据索引从单词表中获取对应的单词。 输出示例:
假设天生的256位熵为:
256位熵(十六进制): b4f5a7c9f8e6d2b1a3c4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6


天生的助记词大概为:
助记词: abandon ability about above absent absorb abstract absurd abuse access

注意事项:
• 完整的BIP39单词表:
在实际开发中,你须要加载完整的2048个单词的BIP39单词表。可以从官方资源或文件中读取。
• 安全性:
确保使用加密安全的随机数天生器(如  os.urandom  或  secrets  模块)来天生熵。
• 校验位的计算:
校验位的长度取决于熵的长度,确保正确计算校验位的长度。
这个代码示例展示了从熵天生助记词的完整过程,你可以根据须要扩展或修改代码以顺应差别的需求。
2.2.碰撞与规复的根本原理

碰撞是指通过随机天生私钥或助记词,与已知的地点进行比对,假如匹配,则以为找到了对应的私钥或助记词。规复则是通过某种机制,从部分信息中重新天生完整的私钥或助记词。我们可以用代码和公式来详细表现“碰撞”和“规复”的过程。以下是两种情况的详细分析和代码实现。
2.2.1.碰撞(Brute-force)

公式描述
碰撞的根本思想是通过随机天生私钥或助记词,然后将其转换为对应的地点,与已知的地点进行比对。假如匹配,则以为找到了对应的私钥或助记词。
公式可以表现为:
随机生成私钥或助记词->转换为地址->比对地址 代码实现:
以下是一个简朴的Python代码示例,展示怎样通过随机天生私钥并转换为地点,然后与已知地点进行比对:
import os
import hashlib
import ecdsa
import binascii

# 示例:已知的地址(以太坊地址为例)
known_address = "0x1234567890abcdef1234567890abcdef12345678"

def private_key_to_address(private_key):
    """
    将私钥转换为以太坊地址
    """
    # 使用ECDSA生成公钥
    sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    public_key = vk.to_string()
   
    # 计算公钥的Keccak-256哈希
    keccak_hash = hashlib.sha3_256(public_key).digest()
   
    # 取哈希的后20字节作为地址
    address = keccak_hash[-20:]
    return "0x" + binascii.hexlify(address).decode()

def brute_force_collision(known_address, num_attempts=1000000):
    """
    随机生成私钥并尝试碰撞
    """
    for _ in range(num_attempts):
      # 随机生成32字节私钥
      private_key = os.urandom(32)
      address = private_key_to_address(private_key)
      
      # 比对地址
      if address.lower() == known_address.lower():
            print("碰撞成功!")
            print("私钥(十六进制):", binascii.hexlify(private_key).decode())
            print("地址:", address)
            return private_key
   
    print("未找到匹配的私钥")
    return None

# 尝试碰撞
brute_force_collision(known_address)
代码剖析:
1. 私钥天生:使用  os.urandom(32)  随机天生32字节的私钥。2. 私钥到地点的转换:使用ECDSA从私钥天生公钥。使用Keccak-256哈希算法计算公钥的哈希值。取哈希值的后20字节作为以太坊地点。3. 碰撞过程:随机天生私钥并转换为地点。将天生的地点与已知地点进行比对。假如匹配,则输出私钥和地点。 2.2.2.规复(Recovery)

公式描述
规复是指通过部分信息(如部分助记词、部分私钥或其他线索)重新天生完整的私钥或助记词。规复过程通常依赖于已知的结构或规则。
公式可以表现为:
已知部分信息->应用恢复规则->生成完整的助记词或私钥 代码实现:
以下是一个简朴的Python代码示例,展示怎样通过部分助记词规复完整的助记词:
import binascii
import hashlib
from mnemonic import Mnemonic

# 示例:已知部分助记词(假设前几个单词已知)
known_partial_mnemonic = ["abandon", "ability", "able", "about"]

# 假设完整的助记词长度为12个单词
mnemo = Mnemonic("english")

def recover_mnemonic(known_partial_mnemonic, wordlist, total_length=12):
    """
    通过部分助记词恢复完整的助记词
    """
    # 获取完整的单词表
    wordlist = mnemo.wordlist
   
    # 尝试补全助记词
    for word1 in wordlist:
      for word2 in wordlist:
            for word3 in wordlist:
                # 构造完整的助记词
                candidate_mnemonic = known_partial_mnemonic +
                if len(candidate_mnemonic) == total_length:
                  # 验证助记词是否有效
                  try:
                        entropy = mnemo.to_entropy(candidate_mnemonic)
                        print("恢复成功!")
                        print("完整的助记词:", " ".join(candidate_mnemonic))
                        print("对应的熵(十六进制):", binascii.hexlify(entropy).decode())
                        return candidate_mnemonic
                  except ValueError:
                        # 如果助记词无效,继续尝试
                        continue
   
    print("未找到有效的助记词")
    return None

# 尝试恢复助记词
recover_mnemonic(known_partial_mnemonic, mnemo.wordlist)
代码剖析:
1. 已知部分助记词:假设已知前几个单词,例如  ["abandon", "ability", "able", "about"]  。2. 规复过程:使用嵌套循环实验补全剩余的单词。使用  Mnemonic  库验证天生的助记词是否有用。假如验证通过,则输出完整的助记词和对应的熵。 3、碰撞技能实现

3.1.随机天生与比对

3.1.1.随机天生:

通过程序随机天生符合BIP39尺度的助记词或私钥。天生助记词时,须要严酷按照熵天生、校验位计算和单词映射的步调。
3.1.2.比对机制:

将天生的助记词或私钥转换为对应的地点,并与预存的地点库进行比对,是区块链开发中常见的一个操作。以下是用Python代码实现这一过程的示例,包括两种情况:
1. 本地存储的地点库:将已知有余额的地点存储在本地文件中。
2. 通过RPC节点实时查询链上地点:使用区块链的RPC接口动态查询地点的余额。
示例代码:
3.1.2.1. 本地存储的地点库

假设我们有一个本地文件  known_addresses.txt  ,此中存储了已知有余额的地点,每行一个地点。
import os
import hashlib
import ecdsa
import binascii

# 示例:从私钥生成以太坊地址
def private_key_to_address(private_key):
    """
    将私钥转换为以太坊地址
    """
    # 使用ECDSA生成公钥
    sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    public_key = vk.to_string()
   
    # 计算公钥的Keccak-256哈希
    keccak_hash = hashlib.sha3_256(public_key).digest()
   
    # 取哈希的后20字节作为地址
    address = keccak_hash[-20:]
    return "0x" + binascii.hexlify(address).decode()

# 从本地文件加载已知地址
def load_known_addresses(file_path):
    with open(file_path, "r") as file:
      known_addresses = file.read().splitlines()
    return known_addresses

# 比对地址
def compare_with_known_addresses(private_key, known_addresses):
    address = private_key_to_address(private_key)
    if address in known_addresses:
      print(f"匹配成功!地址:{address}")
      return True
    return False

# 示例:随机生成私钥并比对
def generate_and_compare():
    known_addresses = load_known_addresses("known_addresses.txt")
    for _ in range(1000000):# 尝试100万次
      private_key = os.urandom(32)# 随机生成32字节私钥
      if compare_with_known_addresses(private_key, known_addresses):
            print(f"私钥:{binascii.hexlify(private_key).decode()}")
            break

# 运行示例
generate_and_compare()
3.1.2.2. 通过RPC节点实时查询链上地点

假设我们使用以太坊的RPC接口(例如Infura)来查询地点的余额。
import os
import hashlib
import ecdsa
import binascii
import requests

# 示例:从私钥生成以太坊地址
def private_key_to_address(private_key):
    """
    将私钥转换为以太坊地址
    """
    sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    public_key = vk.to_string()
    keccak_hash = hashlib.sha3_256(public_key).digest()
    address = keccak_hash[-20:]
    return "0x" + binascii.hexlify(address).decode()

# 使用Infura RPC查询地址余额
def query_address_balance(address, infura_url):
    payload = {
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "params": ,
      "id": 1
    }
    response = requests.post(infura_url, json=payload)
    if response.status_code == 200:
      data = response.json()
      balance = int(data["result"], 16)# 转换为整数
      return balance
    return 0

# 比对地址
def compare_with_rpc(private_key, infura_url):
    address = private_key_to_address(private_key)
    balance = query_address_balance(address, infura_url)
    if balance > 0:
      print(f"匹配成功!地址:{address},余额:{balance}")
      return True
    return False

# 示例:随机生成私钥并比对
def generate_and_compare_rpc():
    infura_url = "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"# 替换为你的Infura项目ID
    for _ in range(1000000):# 尝试100万次
      private_key = os.urandom(32)# 随机生成32字节私钥
      if compare_with_rpc(private_key, infura_url):
            print(f"私钥:{binascii.hexlify(private_key).decode()}")
            break

# 运行示例
generate_and_compare_rpc()
代码剖析:
1. 本地存储的地点库加载地点库从本地文件  known_addresses.txt  中读取已知地点。比对地点将天生的地点与已知地点列表进行比对。随机天生私钥使用  os.urandom(32)  天生随机私钥,并转换为地点。2. 通过RPC节点实时查询链上地点查询地点余额使用Infura的RPC接口查询地点的余额。比对地点假如查询到的地点有余额,则以为匹配乐成。 注意事项:
1. 安全性:
• 确保私钥的天生和存储是安全的,避免走漏。
• 使用加密安全的随机数天生器(如  os.urandom  )。
2. 性能优化:
• 假如使用本地地点库,可以将地点存储在内存中以提高比对速率。
• 假如使用RPC接口,注意API调用的频率限制。
这些代码示例能资助你更好地明确怎样实现私钥到地点的转换以及比对过程!
3.2.碰撞服从优化

3.2.1.算法优化:

在区块链应用中,优化随机数天生算法和地点比对算法是提高服从和安全性的关键。以下将联合搜索结果,详细先容怎样通过算法优化来镌汰无效计算,特别是避免天生不符合钱包规则的私钥。
3.2.1.1.随机数天生算法优化

3.2.1.1.1.选择符合的随机数天生器

在区块链应用中,私钥的安全性至关告急。因此,必须使用加密安全的伪随机数天生器(CSPRNG),而不是平常的伪随机数天生器(PRNG)。CSPRNG天生的随机数具有不可推测性和高随机性,适适用于天生私钥。
3.2.1.1.2.常见的CSPRNG算法包括:

• 操作体系提供的CSPRNG:如  /dev/urandom  (Linux)、  CryptGenRandom  (Windows)。
• 基于暗码学哈希函数的天生器:如SHA-256。
• 专门的加密算法:如ChaCha20。
3.2.​​​​​​​1.1.3.避免天生无效私钥

在某些区块链(如比特币)中,私钥必须满足特定的范围和规则。例如,比特币的私钥是一个256位的随机数,但必须在椭圆曲线的参数范围内(通常为  1  到  n-1  ,此中  n  是椭圆曲线的阶)。为了避免天生无效私钥,可以在天生随机数后进行验证:
import os
import ecdsa

def generate_valid_private_key():
    while True:
      private_key = os.urandom(32)# 生成32字节的随机数
      try:
            # 尝试用私钥生成公钥,验证私钥是否有效
            sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
            return private_key
      except ecdsa.MalformedPointError:
            # 如果私钥无效,重新生成
            continue

# 示例:生成有效的私钥
valid_private_key = generate_valid_private_key()
print("有效的私钥(十六进制):", binascii.hexlify(valid_private_key).decode())
3.2.​​​​​​​1.2.私钥到地点的转换算法优化

3.2.​​​​​​​1.2.1.私钥到公钥的转换

私钥通过椭圆曲线加密算法(如SECP256k1)天生公钥。这个过程是单向的,无法从公钥反推出私钥。
def private_key_to_public_key(private_key):
    sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
    vk = sk.get_verifying_key()
    return vk.to_string()
3.2.​​​​​​​1.2.2.公钥到地点的转换

公钥通过一系列哈希运算和编码天生地点。以以太坊为例,地点的天生过程如下:
-使用SHA-256对公钥进行哈希。
-取哈希值的后20字节作为地点。
def public_key_to_address(public_key):
    keccak_hash = hashlib.sha3_256(public_key).digest()
    address = keccak_hash[-20:]
    return "0x" + binascii.hexlify(address).decode()
3.2.​​​​​​​1.2.3.优化地点天生过程

为了避免重复计算,可以将私钥到地点的整个过程封装成一个函数:
def private_key_to_address(private_key):
    public_key = private_key_to_public_key(private_key)
    address = public_key_to_address(public_key)
    return address
3.2.​​​​​​​1.3.地点比对算法优化

3.2.​​​​​​​1.3.1.本地地点库的比对

假如地点库是本地存储的,可以直接将天生的地点与地点库中的地点进行比对:
def compare_with_known_addresses(private_key, known_addresses):
    address = private_key_to_address(private_key)
    if address in known_addresses:
      print(f"匹配成功!地址:{address}")
      return True
    return False
3.2.​​​​​​​1.3.2.通过RPC节点实时查询

假如地点库是动态的(如通过RPC节点查询),可以使用区块链的RPC接口查询地点的余额:
import requests

def query_address_balance(address, infura_url):
    payload = {
      "jsonrpc": "2.0",
      "method": "eth_getBalance",
      "params": ,
      "id": 1
    }
    response = requests.post(infura_url, json=payload)
    if response.status_code == 200:
      data = response.json()
      balance = int(data["result"], 16)# 转换为整数
      return balance
    return 0

def compare_with_rpc(private_key, infura_url):
    address = private_key_to_address(private_key)
    balance = query_address_balance(address, infura_url)
    if balance > 0:
      print(f"匹配成功!地址:{address},余额:{balance}")
      return True
    return False
3.2.​​​​​​​1.4.算法优化的关键点

3.2.​​​​​​​1.4.1.避免无效计算

• 天生有用的私钥:确保天生的私钥符合区块链的规则。
• 镌汰不须要的哈希计算:在比对过程中,假如地点库是静态的,可以预先计算并存储地点的哈希值,镌汰实时计算。
3.2.​​​​​​​1.4.2.提高比对服从

• 使用高效的字符串比对算法:如Levenshtein距离算法,可以快速判定天生的地点与已知地点的相似度。
• 并行化处置惩罚:使用多线程或多历程同时天生和比对多个私钥,提高服从。
3.2.​​​​​​​1.4.3.安全性思量

• 使用CSPRNG:确保随机数天生器的安全性,防止私钥被推测。
• 掩护私钥:在天生和比对过程中,确保私钥不被走漏。
3.2.​​​​​​​1.5.硬件加速:

使用高性能计算机或GPU加速碰撞过程。GPU的并行计算本事可以显着提高碰撞速率。
. GPU加速的根本原理
GPU(图形处置惩罚单元)具有强盛的并行计算本事,能够同时处置惩罚大量线程。对于碰撞检测或私钥碰撞这类计算麋集型使命,GPU可以显着提高服从。常见的GPU编程框架包括CUDA(NVIDIA)和OpenCL(实用于多种GPU)。
. 情况配置
为了使用GPU加速,你须要以下情况:
- NVIDIA GPU:
支持CUDA的NVIDIA显卡。
-CUDA Toolkit:
用于开发CUDA程序。
-符合的开发情况:
如Visual Studio(Windows)或GCC(Linux)。
CUDA代码示例:
#include <cuda_runtime.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/objects.h>
#include <openssl/bn.h>

// 定义常量
#define THREADS_PER_BLOCK 256
#define TOTAL_KEYS 1000000// 总共尝试的私钥数量

// 从私钥生成以太坊地址(简化版)
__device__ char* privateKeyToAddress(unsigned char* privateKey) {
    // 使用OpenSSL生成公钥
    EC_KEY* eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
    EC_KEY_set_private_key(eckey, BN_bin2bn(privateKey, 32, NULL));
    const EC_POINT* publicKey = EC_KEY_get0_public_key(eckey);

    // 计算公钥的SHA-256哈希
    unsigned char publicKeyHash;
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    unsigned char publicKeyBytes;
    EC_POINT_point2oct(eckey->group, publicKey, POINT_CONVERSION_UNCOMPRESSED, publicKeyBytes, 65, NULL);
    SHA256_Update(&sha256, publicKeyBytes, 65);
    SHA256_Final(publicKeyHash, &sha256);

    // 取哈希的后20字节作为地址
    static char address;
    sprintf(address, "0x");
    for (int i = 12; i < 32; i++) {
      sprintf(&address, "%02x", publicKeyHash);
    }

    EC_KEY_free(eckey);
    return address;
}

// 核函数:生成私钥并检查地址
__global__ void generateKeysAndCheckAddresses(unsigned char* knownAddresses, int numKnownAddresses, int* foundIndex) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx >= TOTAL_KEYS) return;

    unsigned char privateKey;
    for (int i = 0; i < 32; i++) {
      privateKey = (unsigned char)(idx + i);// 简化的随机生成
    }

    char* address = privateKeyToAddress(privateKey);
    for (int i = 0; i < numKnownAddresses; i++) {
      if (strcmp(address, (char*)knownAddresses + i * 42) == 0) {
            foundIndex = idx;
            return;
      }
    }
}

int main() {
    // 已知地址(示例)
    std::vector<char> knownAddresses = {'0', 'x', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f'};
    int numKnownAddresses = knownAddresses.size() / 42;

    // 分配GPU内存
    unsigned char* d_knownAddresses;
    int* d_foundIndex;
    cudaMalloc(&d_knownAddresses, knownAddresses.size() * sizeof(char));
    cudaMalloc(&d_foundIndex, sizeof(int));
    cudaMemcpy(d_knownAddresses, knownAddresses.data(), knownAddresses.size() * sizeof(char), cudaMemcpyHostToDevice);
    cudaMemset(d_foundIndex, -1, sizeof(int));

    // 启动核函数
    int blockSize = THREADS_PER_BLOCK;
    int gridSize = (TOTAL_KEYS + blockSize - 1) / blockSize;
    generateKeysAndCheckAddresses<<<gridSize, blockSize>>>(d_knownAddresses, numKnownAddresses, d_foundIndex);

    // 同步设备
    cudaDeviceSynchronize();

    // 检查结果
    int foundIndex;
    cudaMemcpy(&foundIndex, d_foundIndex, sizeof(int), cudaMemcpyDeviceToHost);
    if (foundIndex != -1) {
      std::cout << "找到匹配的私钥,索引:" << foundIndex << std::endl;
    } else {
      std::cout << "未找到匹配的私钥" << std::endl;
    }

    // 释放GPU内存
    cudaFree(d_knownAddresses);
    cudaFree(d_foundIndex);

    return 0;
}
3.2.​​​​​​​1.6.​​​​​​​分布式计算:

通过分布式体系,将碰撞使命分配到多台计算机上并行实行。
. 分布式体系的根本原理
在分布式体系中,使命被拆分成多个子使命,分配到多台计算机(节点)上并行实行。每个节点独立完身分配给它的使命,并将结果返回给主节点。主节点负责汇总结果并判定是否找到匹配的私钥。
. 技能选型
为了实现分布式碰撞使命,可以使用以下技能:
• Celery:
一个分布式使命队列,支持异步使命和定时使命,适合处置惩罚大规模并发使命。
• Dask:
一个并行计算库,可以将使命分配到多个节点上并行实行。
• 自界说分布式框架:
使用Python的  multiprocessing  模块或C++的多线程/多历程技能
示例代码(Celery配置-创建一个Celery应用,并界说使命:):
# celery_app.py
from celery import Celery

app = Celery('collision_tasks', broker='redis://localhost:6379/0')

@app.task
def generate_and_compare(start_range, end_range, known_addresses):
    """
    生成私钥并比对地址的任务
    """
    import os
    import binascii
    import hashlib
    import ecdsa

    def private_key_to_address(private_key):
      sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
      vk = sk.get_verifying_key()
      public_key = vk.to_string()
      keccak_hash = hashlib.sha3_256(public_key).digest()
      address = keccak_hash[-20:]
      return "0x" + binascii.hexlify(address).decode()

    for i in range(start_range, end_range):
      private_key = os.urandom(32)
      address = private_key_to_address(private_key)
      if address in known_addresses:
            return {"private_key": binascii.hexlify(private_key).decode(), "address": address}
    return None
示例代码(启动Celery Worker-启动Celery Worker以执使用命:):
celery -A celery_app worker --loglevel=info
示例代码(分发使命-在主节点上分发使命并网络结果:):
# main.py
from celery_app import generate_and_compare
import binascii

# 已知地址库
known_addresses = ["0x1234567890abcdef1234567890abcdef12345678"]

# 定义任务范围
total_tasks = 1000000
num_workers = 4
task_size = total_tasks // num_workers

tasks = []
for i in range(num_workers):
    start_range = i * task_size
    end_range = (i + 1) * task_size if i != num_workers - 1 else total_tasks
    tasks.append(generate_and_compare.delay(start_range, end_range, known_addresses))

# 收集结果
results =
for result in results:
    if result:
      print(f"找到匹配的私钥:{result['private_key']},地址:{result['address']}")
      break
else:
    print("未找到匹配的私钥")

4、规复技能实现

4.1.基于机密共享的规复

机密共享技能通过将私钥拆分成多个碎片,并将这些碎片分散存储于差别的节点或区块链上,从而实现私钥的安全管理。在规复过程中,只有网络到足够数量的碎片,才华重新组合出完整的私钥。这种机制显着提拔了安全性:即使部分节点被攻破,攻击者也无法仅凭少数碎片规复出完整的私钥,从而有用掩护了用户的资产和隐私。
机密共享技能的核心思想是将一个机密(例如私钥)拆分成多个碎片,并将这些碎片分散存储。只有网络到足够数量的碎片,才华规复出原始机密。这种技能通常基于Shamir的机密共享算法,它是一种基于多项式插值的暗码学方法。以下是一个使用Python实现Shamir机密共享的示例代码。我们将使用  secretsharing  库来完成这个使命。这个库可以方便地将机密拆分成多个碎片,并从碎片中规复机密。
安装依赖:
起首,你须要安装  secretsharing  库。可以通过以下下令安装:
pip install secretsharing
示例代码:
from secretsharing import SecretSharer

# 原始秘密(例如私钥)
private_key = "0x1234567890abcdef1234567890abcdef12345678"

# 将秘密拆分成多个碎片
# 参数:(n, k) 表示将秘密拆分成 n 个碎片,至少需要 k 个碎片才能恢复秘密
n = 5# 总共拆分成 5 个碎片
k = 3# 至少需要 3 个碎片才能恢复秘密

# 生成碎片
shares = SecretSharer.split_secret(private_key, k, n)

print(f"原始秘密(私钥): {private_key}")
print(f"拆分成 {n} 个碎片,至少需要 {k} 个碎片来恢复秘密。")
print("碎片列表:")
for i, share in enumerate(shares, start=1):
    print(f"碎片 {i}: {share}")

# 恢复秘密
# 假设我们收集到了 3 个碎片
collected_shares = shares[:k]

# 从碎片中恢复秘密
recovered_secret = SecretSharer.recover_secret(collected_shares)

print(f"从碎片中恢复的秘密: {recovered_secret}")
输出示例:
假设原始机密(私钥)为:
原始秘密(私钥): 0x1234567890abcdef1234567890abcdef12345678
拆分成5个碎片,每个碎片大概是雷同以下格式的字符串:
碎片 1: 1-0x1234567890abcdef1234567890abcdef12345678
碎片 2: 2-0x876543210fedcba9876543210fedcba987654321
碎片 3: 3-0xabcdef1234567890abcdef1234567890abcdef
碎片 4: 4-0x1234567890abcdef1234567890abcdef1234
碎片 5: 5-0xfedcba9876543210fedcba9876543210fedcba
从任意3个碎片中规复机密:
从碎片中恢复的秘密: 0x1234567890abcdef1234567890abcdef12345678
代码剖析:
1. 机密拆分:使用  SecretSharer.split_secret  方法将机密拆分成多个碎片。参数  (k, n)  表现将机密拆分成  n  个碎片,至少须要  k  个碎片才华规复机密。每个碎片是一个字符串,包含一个索引和对应的加密数据。2. 机密规复:网络至少  k  个碎片。使用  SecretSharer.recover_secret  方法从碎片中规复原始机密。 安全性上风:
• 分散存储:
机密被拆分成多个碎片,分别存储在差别的节点或区块链上,镌汰了单点故障的风险。
• 容错性:
即使部分碎片丢失或被攻破,只要网络到足够的碎片,仍然可以规复原始机密。
• 高安全性:
即使攻击者获取了部分碎片,也无法规复完整的机密,除非他们网络到足够的碎片数量。
这种技能在区块链和分布式体系中非常有用,可以有用掩护私钥和其他敏感信息的安全。
4.2.基于生物特征的规复

使用用户的生物特征(如指纹、虹膜等)天生私钥掩护的密钥。在规复时,通过验证生物特征,解密存储的私钥碎片,从而规复完整的私钥。这种方法联合了生物特征的唯一性和暗码学的安全性,提供了较高的规复安全性。
4.3.基于多方安全计算的规复

多方安全计算技能允很多个到场方在不走漏各自隐私的情况下,共同完成私钥的规复。例如,用户和密钥管理服务商通过协同计算,对私钥进行加密息争密。这种方法可以有用防止单点故障和隐私走漏。
5、技能挑衅与办理方案

5.1.碰撞概率极低

由于私钥和助记词的组合数量极其巨大,碰撞乐成的概率极低。例如,12个单词的助记词有\(2048^{12}\)种大概。办理方案包括:
• 提高碰撞速率,通过优化算法和硬件加速。
• 增长地点库的规模,提高碰撞的大概性。
5.2.安全性标题

碰撞和规复过程中存在被攻击的风险,大概导致用户资产被盗。办理方案包括:
• 在无网络情况下运行碰撞程序。
• 对存储的私钥碎片进行加密。
• 引入身份验证机制,确保只有合法用户可以规复私钥。
5.3.性能与服从标题

碰撞和规复过程须要大量的计算资源和时间。办理方案包括:
• 接纳分布式计算和GPU加速。
• 优化算法,镌汰无效计算。
希望这篇文章对你有所资助。假如你尚有其他标题,欢迎继续向我提问,Goldenkey专业开发区块链加密/解密技能。TG:@hebe7956  @Gdk7956

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Goldenkey教你开发区块链助记词&密钥碰撞/规复器