主页 > tp钱包导入imtoken > 比特币地址是如何产生的

比特币地址是如何产生的

tp钱包导入imtoken 2023-04-25 06:01:40

手动生成比特币地址似乎有点费力。 如果你了解这个过程,你就会明白,眼花缭乱的比特币分叉地址只是私钥的另一种显示方式。 了解Eth EOS地址也很有帮助,可以更清楚的了解比特币是怎么...

手动生成比特币地址似乎有点费力。 如果你了解这个过程,你就会明白,眼花缭乱的比特币分叉地址只是私钥的另一种显示方式。 了解Eth EOS地址也很有帮助,可以更清楚地知道比特币是怎么花的,是知乎的好方法。

我们使用私钥 0xccea9c5a20e2b78c2e0fbdd8ae2d2b67e6b1894ccb7a55fc1de08bd53994ea64 生成了主网地址 14xfJr1DArtYR156XBs28FoYk6sQqirT2s。

生成比特币地址,首先由私钥生成公钥,然后由公钥生成hash160比特币地址是如何产生的,最后对hash160进行base58运算得到地址,如下图:

比特币qt钱包发币地址_火币网比特币提现地址_比特币地址是如何产生的

从私钥中获取公钥是由ECDSA实现的。 ECDSA是Elliptic Curve Digital Signature Algorithm的缩写,即椭圆曲线数字签名算法。

椭圆曲线实际上不是椭圆,但看起来像这样:

火币网比特币提现地址_比特币地址是如何产生的_比特币qt钱包发币地址

比特币使用的椭圆曲线是secp256k1: $y^2=x^3+7$ 那么言归正传,直接进入正题。 我把这个过程分为8个步骤。

第1步。 生成私钥

比特币需要使用特殊的椭圆曲线 Secp256k1 来获取公钥和私钥。 我们通过 OpenSSL 命令生成私钥。

openssl ecparam -name secp256k1 -genkey > priv.pem
# 输出DER格式
openssl ec -in priv.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32
# 结果
ccea9c5a20e2b78c2e0fbdd8ae2d2b67e6b1894ccb7a55fc1de08bd53994ea64

这里的结果是一个十六进制数据 0xccea9c5a20e2b78c2e0fbdd8ae2d2b67e6b1894ccb7a55fc1de08bd53994ea64

更快的方法是 openssl rand 32 -hex

第2步。 生成公钥

通过priv.pem生成pub_key

openssl ec -in priv.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65
# 输出
04d061e9c5891f579fd548cfd22ff29f5c642714cc7e7a9215f0071ef5a5723f691757b28e31be71f09f24673eed52348e58d53bcfd26f4d96ec6bf1489eab429d

输出DER格式, 字符长度是130pub_key = 04d061e9c5891f579fd548cfd22ff29f5c642714cc7e7a9215f0071ef5a5723f691757b28e31be71f09f24673eed52348e58d53bcfd26f4d96ec6bf1489eab429d这是未压缩公钥,压缩公钥是03d061e9c5891f579fd548cfd22ff29f5c642714cc7e7a9215f0071ef5a5723f69

一步生成私钥和公钥

openssl ecparam -genkey -name secp256k1 -text -noout -outform DER | \
xxd -p -c 1000 | \
sed 's/41534e31204f49443a20736563703235366b310a30740201010420/PrivKey: /' | \
sed 's/a00706052b8104000aa144034200/\'$'\nPubKey: /'

详见压缩公钥和未压缩公钥

第三步。 对步骤2的结果进行hash160计算

hash160运算是先进行SHA256,再进行RMD160。

bytes = [pub_key].pack("H*") # 转为16进制
hash160_val = Digest::RMD160.hexdigest(Digest::SHA256.digest(bytes) )

hash160_val = 2b6f3b9e337cedbb7c40839523fb1100709c12f7

第四步。 步骤3的结果是前缀

常见的主网地址前缀是00,比特币地址前缀有很多种,见

'00'+ '2b6f3b9e337cedbb7c40839523fb1100709c12f7'

step_04 = 002b6f3b9e337cedbb7c40839523fb1100709c12f7

第五步。 Step 4的结果,执行两次SHA256,取前8位作为校验和

hex_str = [step_04].pack("H*")
checksum = Digest::SHA256.hexdigest(Digest::SHA256.digest(hex_str) )[0...8]

校验和 = 86b2e90c

第六步。 将步骤 4 的结果与步骤 5 的结果合并

'002b6f3b9e337cedbb7c40839523fb1100709c12f7' + '86b2e90c'
# step_04 + checksum

step_06 = 002b6f3b9e337cedbb7c40839523fb1100709c12f786b2e90c

第七步。 Base58编码

Base58是一种独特的编码方式,是Base64的变形,主要用于比特币钱包地址。 与Base64相比,Base58去除了数字0、大写字母O、大写字母I、小写字母l、+和/以避免视觉上的混淆。

来个base58算法

def encode_base58(int_val, leading_zero_bytes=0)
  alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
  base58_val, base = '', alpha.size
  while int_val > 0
    int_val, remainder = int_val.divmod(base)
    base58_val = alpha[remainder] + base58_val
  end
  base58_val
end

第八步。 第6步的结果是base58编码的

step_06 = "002b6f3b9e337cedbb7c40839523fb1100709c12f786b2e90c"
leading_zero_bytes = (step_06.match(/^([0]+)/) ? $1 : '').size / 2
# leading_zero_bytes的作用是字母填充
address = ("1" * leading_zero_bytes) + encode_base58(step_06.to_i(16) )

得到14xfJr1DArtYR156XBs28FoYk6sQqirT2s,这是一个标准的比特币地址,终于大功告成了。

思考:hash160_val能否通过比特币地址逆向?

摘要代码:gen_addr.rb

可以使用 bitcoin-ruby 生成地址

require 'bitcoin'
pri_key, pub_key = Bitcoin.generate_key # 私钥 公钥
# 通过ffi调用OpenSSL得到,很多类库都是这么做的
address = Bitcoin::pubkey_to_address(pub_key)

生成测试网地址

require 'bitcoin'
Bitcoin::network = :testnet #使用测试网
pri_key, pub_key = Bitcoin.generate_key
address = Bitcoin::pubkey_to_address(pub_key)

在比特币系统中,私钥可以得到公钥,公钥可以得到钱包地址,私钥=>公钥=>钱包地址,反过来是不行的。 请牢记您的私钥,私钥不可修改,地址不可修改。 谁拥有私钥,谁就拥有硬币!!!

参考:

这些 OpenSSL 命令如何从 ECDSA 密钥对创建比特币私钥/密钥如何将 ECDSA 密钥转换为 PEM 格式

本文参与登联社区写作激励计划,好文章好收益比特币地址是如何产生的,欢迎正在阅读的你加入。