openssl-and-btc-address

公钥生成参考这里

摘要算法ripemd160无法生效的问题,解决方法:在后面增加 -provider legacy 即可
如:我在看btc地址官方文档时,使用ripemd160做摘要,一直无法生效,报错信息为:
Error setting digest
4017D072897F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (RIPEMD160 : 99), Properties ()
4017D072897F0000:error:03000086:digital envelope routines:evp_md_init_internal:initialization error:../crypto/evp/digest.c:254:

就用这个方法解决的。

btc地址生成步骤:

How to create Bitcoin Address

The correct way to create a Bitcoin address is to use well tested, open source, peer reviewed wallet software. Manually handling keys has resulted in funds loss over and over again. Unlike other centralized systems losses in Bitcoin are usually unrecoverable.

Here is a brief overview of how address generation works, for informational purposes:

0 - Having a private ECDSA key

   18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725

1 - Take the corresponding public key generated with it (33 bytes, 1 byte 0x02 (y-coord is even), and 32 bytes corresponding to X coordinate)

   0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352

2 - Perform SHA-256 hashing on the public key

   0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98

3 - Perform RIPEMD-160 hashing on the result of SHA-256

   f54a5851e9372b87810a8e60cdd2e7cfd80b6e31

4 - Add version byte in front of RIPEMD-160 hash (0x00 for Main Network)

   00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31

(note that below steps are the Base58Check encoding, which has multiple library options available implementing it)
5 - Perform SHA-256 hash on the extended RIPEMD-160 result

   ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c

6 - Perform SHA-256 hash on the result of the previous SHA-256 hash

   c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd

7 - Take the first 4 bytes of the second SHA-256 hash. This is the address checksum

   c7f18fe8

8 - Add the 4 checksum bytes from stage 7 at the end of extended RIPEMD-160 hash from stage 4. This is the 25-byte binary Bitcoin Address.

   00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8

9 - Convert the result from a byte string into a base58 string using Base58Check encoding. This is the most commonly used Bitcoin Address format

   1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs



以上示例中,私钥为:18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725

1、压缩公钥生成方法:
这里找到一个根据openssl和私钥文件生成公钥的方法,
但根据一个私钥字符串来生成公钥,用shell还没找到办法,python倒是可以的。

2、在公钥上做sha256计算:
[vagrant@vm-node1:btc]$ echo -n "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" | xxd -r -p |sha256sum
0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98  -

3、在步骤2基础上做ripemd160运算:
[vagrant@vm-node1:btc]$ echo -n "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" | xxd -r -p |sha256sum  | xxd -r -p |  openssl dgst -provider legacy -rmd160
RIPEMD-160(stdin)= f54a5851e9372b87810a8e60cdd2e7cfd80b6e31

tips: 注意每次计算出一个结果后,都需要用xxd将其转变一下才可以继续进行后续计算

4、在步骤3基础上增加主网版本号0x00
00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31

5、在步骤4基础上做sha256运算
此处用的openssl做sha256运算,用法是:openssl dgst -sha256
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl dgst -sha256
SHA2-256(stdin)= ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c


当然可以直接使用sha256sum,结果是一样的:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | sha256sum
ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c  -

或者使用openssl sha256: 
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl sha256
SHA256(stdin)= ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c


6、在步骤5的基础上继续做sha256运算
第5步的结果是:ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c

[vagrant@vm-node1:btc]$ echo -n "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c" | xxd -r -p| openssl sha256
SHA256(stdin)= c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd

使用openssl sha256和openssl dgst -sha256效果一样
或者使用sha256sum也可以

[vagrant@vm-node1:btc]$ echo -n "ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c" | xxd -r -p| sha256sum
c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd  -

以下是生成第5步和要得到第6步给连起来了。
两次使用sha256sum,得到的结果和上面一致:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | sha256sum | xxd -r -p | sha256sum
c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd  -

但两次连续使用openssl,得到的结果不一样:
两次使用openssl sha256:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl dgst -sha256 | xxd -r-p | openssl dgst -sha256
SHA2-256(stdin)= a8ab134ca5d4ff31cc82027844dc9d909bc4e0c994de9bd331f031e9cb89e0c6

两次使用openssl dgst -sha256
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl sha256 | xxd -r -p | openssl sha256
SHA256(stdin)= ed8402fddbabba069c22f44bc47b2dc75f3fa3bdde33b727f7f0d2e7c0a38d2c

尝试对上面两个出错误结果的语句做了下修改,将第一次调用openssl的结果用awk做了下处理,仅仅输出"="后面的东西
两次使用openssl sha256:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl dgst -sha256 | awk -F"=" '{print $2}' | xxd -r -p | openssl dgst -sha256
SHA2-256(stdin)= c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd


两次使用openssl dgst -sha256
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | openssl sha256 | awk -F"=" '{print $2}' | xxd -r -p | openssl sha256
SHA256(stdin)= c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd

这次终于跟直接直接调用sha256sum的结果一致了,很奇怪,连续两次调用sha256sum,第一次的结果不管是否用awk处理,都能得到正确的结果
未使用awk:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | sha256sum | xxd -r -p | sha256sum
c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd  -

使用了awk:
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" | xxd -r -p | sha256sum | awk '{print $1}' | xxd -r -p | sha256sum
c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd  -

看来以后尽量直接用sha256sum吧,尤其是需要连续多次执行sha256运算时


7、取前四个字节:
c7f18fe8

8、将第4个步骤和第7个步骤的结果连接起来,这个是25字节的btc地址
第4个步骤:00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
第7个步骤:c7f18fe8
连起来就是:00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8

9、对第8步骤的结果进行base58运算
[vagrant@vm-node1:btc]$ echo -n "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8" | xxd -r -p |  base58
1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs