来自

bitcoin地址是如何生成的​www.jianshu.com

btc address: 1FmWXNJT3jVKaHBQs2gAs6PLGVWx1zPPHf

手动生成Bitcoin地址看似有点儿事倍功半,如果你了解了这个过程,就会明白眼花缭乱的Bitcoin分叉币地址只是私钥的不同显示方式,对了解Eth EOS地址也很有帮助,也可以更清楚的了解Bitcoin是如何花费的,一通则百通,妙哉。

生成Bitcoin地址,先由私钥生成公钥,再有公钥生成hash160,最后hash160再进行base58运算得到地址,如下图所示:

生成私钥,再得到公钥,是由ECDSA实现的。ECDSA是Elliptic Curve Digital Signature Algorithm的缩写, 即椭圆曲线数字签名算法

椭圆曲线其实不是椭圆,而是下面的模样:

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

Step1. 生成私钥

Bitcoin要使用到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

这里的结果是个16进制数据 0xccea9c5a20e2b78c2e0fbdd8ae2d2b67e6b1894ccb7a55fc1de08bd53994ea64

Step2. 生成公钥

通过priv.pem 生成 pub_key

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

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

详细内容请看压缩公钥与非压缩公钥

Step3. 第2步结果进行hash160运算

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

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

hash160_val = 2b6f3b9e337cedbb7c40839523fb1100709c12f7

Step4. 第3步结果加上前缀符

普通的主网地址的前缀符是00,Bitcoin 地址前缀符有很多种, 具体看https://en.bitcoin.it/wiki/List_of_address_prefixes

'00'+ '2b6f3b9e337cedbb7c40839523fb1100709c12f7'

step_04 = 002b6f3b9e337cedbb7c40839523fb1100709c12f7

Step5. 第4步结果, 执行2次SHA256, 取前8位作为校验和

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

checksum = 86b2e90c

Step6. 第4步结果跟第5步结果合并

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

step_06 = 002b6f3b9e337cedbb7c40839523fb1100709c12f786b2e90c

Step7. Base58编码

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

来个base58算法

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

Step8. 第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,这是一个标准的bitcoin地址,终于大功告成。

思考:通过Bitcoin 地址能反向得到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)

在Bitcoin系统中,私钥能得公钥,公钥能得到钱包地址, 私钥=>公钥=>钱包地址,而反向是不可以的。 牢记你的私钥,而且私钥不能修改地址也不能修改,谁掌握了私钥谁就拥有了这些币!!!


参考:

https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses

https://en.bitcoin.it/wiki/Address

https://en.bitcoin.it/wiki/List_of_address_prefixes

https://github.com/liushooter/learn-blockchain/blob/master/gen_addr.rb

keypairgenerator生成的公钥是不变的么_bitcoin 地址是如何生成的相关推荐

  1. 数字证书、数字签名的实现使用以及keytool工具生成私钥公钥

    数字证书.数字签名的实现使用以及keytool工具生成私钥公钥 数字签名 数字证书 数字签名的实现 keytool工具 基本命令 生成私钥公钥 导出公钥 数字签名 数字签名(又称公钥数字签名)是只有信 ...

  2. 使用RSA生成一对公钥和私钥

    使用RSA生成一对公钥和私钥 package com.demoinfo.support.utils;import sun.misc.BASE64Decoder; import sun.misc.BAS ...

  3. Mac系统Git生成ssh公钥

    Mac系统Git生成ssh公钥 在使用Git仓库进行代码管理时,新的电脑上往往需要生成ssh公钥进行匹配,Mac系统生成Git公钥过程如下: 1.检查本机是否已有公钥 在终端中输入如下命令: ? 1 ...

  4. Git: 生成ssh公钥

    生成 SSH 公钥 大多数 Git 服务器都会选择使用 SSH 公钥来进行授权.系统中的每个用户都必须提供一个公钥用于授权,没有的话就要生成一个.生成公钥的过程在所有操作系统上都差不多. 首先先确认一 ...

  5. git 拉去代码要求密码 解决方法:生成gitLab公钥

    git 拉去代码要求密码 解决方法:生成gitLab公钥 参考文章: (1)git 拉去代码要求密码 解决方法:生成gitLab公钥 (2)https://www.cnblogs.com/songya ...

  6. java中使用openssl生成的rsa公私钥进行数据加解密_使用openssl生成RSA公钥和私钥对...

    在ubuntu上要使用openssl的话需要先进行安装,命令如下: sudo apt-get install openssl 安装完成就可以使用openssl了. 首先需要进入openssl的交互界面 ...

  7. daoi php_使用php生成RSA公钥私钥及进行加密解密和签名验证

    这篇文章主要介绍使用PHP开发接口,数据实现RSA加密解密后使用,实例分析了PHP自定义RSA类实现加密与解密的技巧,非常具有实用价值,需要的朋友可以参考下. 简单介绍RSA: RSA加密算法是最常用 ...

  8. java rsaprivatekey_用ssh-keygen生成的公钥和私钥如何在java中转为RSAPublicKey和RSAPrivateKey...

    公钥和私钥是用"ssh-keygen -t rsa"生成的,我把生成的公钥以字符串的形式传入下面的函数(从网上找的)就会报错. public static PublicKey st ...

  9. Git笔记(19) 生成SSH公钥

    Git笔记(19) 生成SSH公钥 1. SSH公钥认证 2. 密钥 3. 公钥 1. SSH公钥认证 许多 Git 服务器都使用 SSH 公钥进行认证 如果某系统用户尚未拥有密钥,必须事先为其生成一 ...

最新文章

  1. JoshChen判断是否微信内置浏览器访问【转载】
  2. mount: 未知的文件系统类型“vboxsf”_第六章--文件系统管理
  3. 都是套路:高并发系统的降级特技
  4. BigDecimal丢失精度的坑
  5. 根据用户id查询菜单列表(菜单权限问题)
  6. bzoj4513 [Sdoi2016]储能表 dp
  7. 项目经理应如何调动员工的积极性
  8. openfire源码编译后部署到linux
  9. jQuery has(),not()和filter()函数示例
  10. 解决64位进程调用32位库文件报错问题
  11. 【已解决】 c8812在eclipse上调试打不出log来?求帮助如何解决?!!!
  12. [拓扑资料汇总-近期更新中]点集代数拓扑 与泛函共看效果更佳
  13. 原型设计工具——axure认识与使用
  14. 用标签打印软件将Excel中的多列数据合并打印
  15. 抖音多画面分屏PR分屏预设 横板竖版手机短视频分屏效果PR预设下载
  16. 焦距相关的基本概念及焦距对摄影效果的影响
  17. Arduino ESP32通过心知天气获取城市三天的信息
  18. PHP学习笔记(二)——行云博客
  19. 电子护照阅读器解决方案
  20. Java实现Zip压缩包解压

热门文章

  1. 华为海外女科学家为您揭秘:GaussDB(for MySQL)云栈垂直集成的力量有多大?
  2. 知道ThreadLocal吗?一起聊聊到底有啥用
  3. 机器学习入门:多变量线性回归
  4. 华为云IoT智简联接,开启物联世界新纪元
  5. 从零开始:什么是Makefile分析
  6. 快速了解云原生中的微服务应用(内含福利)
  7. 前端常用60余种工具方法(上)
  8. M1芯片Mac使用原生brew安装软件速度过慢的解决办法
  9. jieba分词 ‘float‘ object has no attribute ‘decode‘ 解决方法
  10. php集成是什么原因,PHP集成开发环境里面的www问题