Shooter:从椭圆曲线到比特币地址

从椭圆曲线到比特币地址

1. 从椭圆曲线到比特币地址 S h o o t e r @ N E RV O S 北北 京
2. 01 椭圆曲线
3. 总体过程 箭头表示过程是否可逆
4. ECC ⽣生成私钥,再得到公钥,是由ECDSA实现的。 ECDSA就是 Elliptic Curve Digital Signature Algorithm, 即椭圆曲线数字签名算法。 ECDSA 在https中可以启⽤用,据说也⽤用在中国⼤大陆的⼆二代身份证上
5. ECC y 2 = ax 3 + b
6. ECC secp256k1 a=1b=7 y2 = x3 + 7
7. ECC加法 加法计算公式:P+Q=R
8. ECC倍乘 乘法计算公式:P+P=2P,在P处做切线
9. ECC 多倍乘法
10. ECC有限域 椭圆曲线是连续的,并不不适合⽤用于加密;所以,我们必须把椭 圆曲线变成离散的点,要把椭圆曲线定义在有限域上。 有限域表示: 𝔽p 7,11,13,29,233 都是质数, 𝔽233
11. ECC有限域计算 𝔽233 y 2 mod 233 = x 3 + 7 mod 233 y 2 % 233 = x 3 + 7 % 233
12. secp256k1 有限域为: Pcurve = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f 2256 − 232 − 29 − 28 − 27 − 26 − 24 − 1 这个数⾮非常、⾮非常、⾮非常、⾮非常、⾮非常、⾮非常、⾮非常⼤大, 假设在⼀一个cpu时钟周期内就能完成⼀一次循环, 循环Pcurve次要花多⻓长时间呢?
13. secp256k1 群的阶: N=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF4 8A03BBFD25E8CD0364141 从1~N的范围内其实都能当做私钥, 为了了安全,要有64位⻓长度,私钥要⼩小于N
14. secp256k1 ⽣生成点:G Point Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b1 6f81798 Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb 10d4b8 从这个点开始, 运⾏行行k*G,k为私钥,k*G的结果就是公钥
15. secp256k1 openssl prime 11579208923731619542357098500868790785326 9984665640564039457584007908834671663 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFEFFFFFC2F is prime 判断Pcurve是否为质数
16. 理论完成,画马
17. secp256k1 随机得到⼀一个私钥: 0xccea9c5a20e2b78c2e0fbdd8ae2d2b67e6b1894ccb7a55 fc1de08bd53994ea64
18. Ruby Code https://github.com/NervosBeijingCommunity/jupyter-ppt/blob/master/RubySaturday20190309/code/ecc-secp256k1.rb
19. 02 生成地址
20. 总体过程 整个过程都不不需要联⽹网
21. hash160运算 bytes = [pub_key].pack("H*") # 转为16进制 hash160_val = Digest::RMD160.hexdigest(Digest::SHA256.digest(by tes) )
22. 前缀符 '00'+ '2b6f3b9e337cedbb7c40839523fb1100709c12f7' 前缀符有很多种 00, 05, 6f
23. 校验和 执⾏行行2次SHA256, 取前8位作为校验和 hex_str = [step_04].pack("H*") checksum = Digest::SHA256.hexdigest(Digest::SHA256.digest(h ex_str) )[0...8]
24. 第4步结果跟第5步结果合并 '002b6f3b9e337cedbb7c40839523fb1100709c12f7' + '86b2e90c' # step_04 + checksum
25. Base58编码 def encode_base58(int_val, leading_zero_bytes=0) alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwx yz" 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
26. 计算出地址 step_06 = "002b6f3b9e337cedbb7c40839523fb1100709c12f786b2e 90c" 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
27. 生成地址 更更多详细介绍:https://www.jianshu.com/p/954e143e97d2
28. 03 燃烧地址
29. 燃烧地址 我们得知hash160是计算出来的,这样计算出来的地址 才有对应的私钥,才能动⽤用这个地址的资⾦金金 假设就把hash160设定为 0000000000000000000000000000000000000000, 从半截腰上计算,我们并不不知道这个地址的私钥, ⽆无法动⽤用这个地址的资⾦金金,这就是燃烧地址 Hash后的数据是⽆无规律律的,越是有规律律的数据, 动⽤用的计量量越⼤大,越很难得到
30. 燃烧地址 1111111111111111111114oLvT2 的hash160是 0000000000000000000000000000000000000000 12ZEw5Hcv1hTb6YUQJ69y1V7uhcoDz92PH的 hash160是 1111111111111111111111111111111111111111 这2个地址都是这样得到的,从交易易记录看,只有输⼊入记 录,没有输出记录,它们是燃烧地址 更更多介绍:https://www.jianshu.com/p/cc9e651faca4
31. 03 靓号地址
32. 靓号地址 1SNiPeRGTJuELpHRDTRzg7A64weBCWpNq => sniper 1LoveYoURwCeQu6dURqTQ7hrhYXDA4eJyn => 1LoveYoU Hash后的数据是⽆无规律律的,越是有规律律的数据, 动⽤用的计算量量越⼤大,这是⼀一种标识,也是实⼒力力的象征
33. 04 骚操作:同一份私钥得到以太坊地址
34. 骚操作 以太坊也是使⽤用Secp256k1椭圆曲线得到私钥、公 钥,跟⽐比特币使⽤用的算法完全相同
35. 骚操作 ⽤用之前得到同⼀一份公钥⽣生成eth地址 04d061e9c5891f579fd548cfd22ff29f5c64 2714cc7e7a9215f0071ef5a5723f691757b2 8e31be71f09f24673eed52348e58d53bcfd2 6f4d96ec6bf1489eab429d
36. 骚操作 0x9156a7cdab767ffe161ed21a0cb0b688b545b01f 14xfJr1DArtYR156XBs28FoYk6sQqirT2s 不不同的地址是同⼀一份私钥,地址就像语法糖 这给资产管理理带来⼀一些⽅方便便,但如果⼀一份私钥泄露露, 2份资产都有可能被盗。 管理理⼀一时爽,泄露露全都⽕火葬场 更更多资料料:https://www.jianshu.com/p/d3837398f69c
37. Thanks S h o o t e r @ N E RV O S 北北 京
详细代码:https://github.com/NervosBeijingCommunity/jupyter-ppt/tree/master/RubySaturday20190309
2019/03/10