openssl-bitcoin-address

0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d

wif:5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ

wif_compressed:KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617

pub_key_hex: 04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a

pub_key_hex_compressed: 02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

p2pkh_compressed_addr:1LoVGDgRs9hTfTNJNuXKSpywcbdvwRXpmK

p2pkh_addr:1GAehh7TsJAHuUAeKZcXf5CnwuGuGgyX2S

p2wpkh-p2sh: bc1qmy63mjadtw8nhzl69ukdepwzsyvv4yex5qlmkd

p2sh: 3D9iyFHi1Zs9KoyynUfrL82rGhJfYTfSG4

p2psh: 3GrfdEbuRCUfzds5SfH85hZj6RZctF5Nfg 


本文使用的私钥为: 0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d

对应的WIF: 5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ

压缩WIF: KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617

未压缩公钥:  04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a

压缩公钥: 02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

可以在这里校验结果,在这里输入私钥之后,可以用于校验每步的结果
tips: 这个页面生成地址时的步骤是正确的,但结果似乎有问题,慎重!!!

不同类型地址的主网信息和脚本类型可以参考这个页面,下面摘抄一部分吧
------------------------开始------------------------

公钥生成地址过程

  1. 不同的锁定脚本依赖的源数据生成。对应关系如下
脚本类型源类型地址长度
P2PKH公钥20
P2SH脚本20
P2WPKH公钥20
P2WSH脚本32
P2SH-P2WSH公钥20
P2SH-P2WPKH脚本20
  1. 地址的表现形式

实际上我们看到的地址是经过Bash58编码或bech32编码的地址,地址中添加了地址类型和校验码所以不同的地址开头会呈现不同的数值。生成锁定脚本的时候要解码数据并且去掉地址类型码。

不同地址的标志位对照表如下:

地址类型网络类型对应的地址标志位编码类型说明
P2PKH地址main0x00Base58支付到比特币地址的交易包含支付公钥哈希脚本(P2PKH)。由P2PKH 脚本锁定

的交易输出可以通过给出由相应私钥创建的公钥和数字签名来解锁(消费)

testnet0x6FBase58
regtest0x6FBase58
P2SH地址main0x05Base58P2SH 地址是基于Base58 编码的一个含有20 个字节哈希的脚本。P2SH 地址采用

“5”前缀。这导致基于Base58 编码的地址以“3”开头。P2SH 地址隐藏了所有的复

杂性,因此,运用其进行支付的人将不会看到脚本。

testnet0xC4Base58
regtest0xC4Base58
P2WPKH地址main“bc”Bech32P2WPKH地址是脚本做HASH160得到20位的地址经过Bech32编码后显示
testnet“tb”Bech32
regtest“bcrt”Bech32
P2WSH地址main“bc”Bech32P2WSH地址是脚本做HASH256得到到32位的地址经过Bech32编码后显示
testnet“tb”Bech32
regtest“bcrt”Bech32
P2SH-P2WPKH地址main0x05Base58P2SH-P2WPK地址是为了满足旧钱包的需求,将P2WPKH对应的锁定脚本转换到普通的P2SH地址格式。
testnet0xC4Base58
regtest0xC4Base58
P2SH-P2WSH地址main0x05Base58P2SH-P2SH地址是为了满足旧钱包的需求,将P2WPKH对应的锁定脚本转换到普通的P2SH地址格式。
testnet0xC4Base58
regtest0xC4Base58

锁定脚本的结构

P2PKH:

是利用公钥的哈希,相对来说比较简单,现在新版本的钱包应用的越来越少。

OP_DUP OP_HASH160 OPCODE_LEN ADDR OP_EQUALVERIFY OP_CHECKSIG

对应的字节表示 0x76 0xa9 0x14 20字节地址 0x88 0xac

P2PKH长度:25字节

OPCODE_LEN:0x14 即 地址ADDR的长度

ADDR:是由公钥生成的20字节

P2SH:

利用了脚本的哈希,并且锁定脚本相较于P2PKH更加简洁。由于脚本更加复杂,可以根据需要设计不同的逻辑控制,因此应用会被广泛应用。锁定脚本中表示简单,但是赎回脚本和签名处变的复杂了。

OP_HASH160 OPCODE_LEN ADDR OP_EQUAL

对应的字节表示: 0xa9 0x14 20字节地址 0x87

P2SH长度:23

OPCODE_LEN:0x14 即 地址ADDR的长度

ADDR:是由脚本经过HASH160生成的20字节

P2WPKH:

是隔离见证中公钥地址的表示,格式主要是为了与非隔离见证的锁定脚本区别。旧钱包是不支持的。

VER OPCODE_LEN ADDR

对应的字节表示 0x00 0x14 20字节地址

P2WPKH长度:22

0x00: 版本号,固定0

OPCODE_LEN:0x14 即 地址ADDR的长度

ADDR:是由公钥生成的20字节

P2WSH:

是隔离见证中脚本地址的表示,格式主要是为了与非隔离见证的锁定脚本区别。旧钱包是不支持的。因为可以用到复杂脚本,因此可以做复杂逻辑应用。

VER OPCODE_LEN ADDR

对应的字节表示 0x00 0x20 32字节地址

P2WSH长度:34

0x00: 版本号,固定0

OPCODE_LEN:0x20 即 地址ADDR的长度

P2SH-P2WPKH:

P2SH-P2WPKH是对P2WPKH进行HASH160得到20字节地址,此地址可在P2SH中应用,与普通的P2SH地址没有任何区别。格式见P2SH

P2SH-P2WSH

P2SH-P2WSH是对P2WSH进行HASH160得到20字节地址,此地址可在P2SH中应用,与普通的P2SH地址没有任何区别。格式见P2SH

比特币地址类型:

比特币地址类型分为3中格式: legacy p2sh-segwit bech32

legacy类型实际上就是取公钥或脚本的HASH160值得到20位字节地址。

p2sh-segwit:对应生成P2SH-P2WPKH 和 P2SH-P2WSH中的地址

bech32:对应生成P2WPKH 和 P2WSH中的地址

隔离见证中的公钥类型

隔离见证中生成地址用到的公钥必须是压缩的公钥,否则可能会无法赎回此地址的币。

隔离见证地址用长度32或20来判定地址是由脚本或公钥生成的,0(版本)开头表示是隔离见证地址。

脚本中的地址和钱包中的地址区别

我们在UI上看到的地址是带有地址类型码并且经过Bash58或Bech32编码后的地址的字符串,因此与实际地址长度并不符合。当我们传入此地址后,会解码并去除类型码,并根据类型码生成不同的ScriptPubkey(P2PKH P2SH P2WSH P2WPKH P2SH-P2WSH P2SH-P2WPKH)。

各种地址样子如下:

P2PKH地址:

显示的地址:mgjswfb6eXcmuJgLxvMxAo1tth2QCyyPYt

实际地址16进制表示:0x0d 0x69 0xe6 0x9c 0x75 0x72 0x53 0x4c 0xa3 0x5d 0xdd 0x12 0x64 0x6f 0x90 0x8b 0xf0 0x7b 0xf7 0xb6

P2SH地址:

显示的地址:2Mz5nE8zyxQDMZawYZ6cqbHZZdkih5CwQjU

实际地址16进制表示:0x4a 0xff 0xa1 0xed 0x45 0x54 0x17 0x5a 0x00 0xd6 0x54 0x78 0x8d 0x34 0xf3 0x13 0xd7 0x38 0x02 0xdd

P2WSH地址:

显示的地址:bcrt1qja4c5mpjw8hjlatgwud56naunfykxwupk65yev

实际地址16进制表示:0x14 0x97 0x6b 0x8a 0x6c 0x32 0x71 0xef 0x2f 0xf5 0x68 0x77 0x1b 0x4d 0x4f 0xbc 0x9a 0x49 0x63 0x3b 0x81

P2WPKH地址:

显示的地址:bcrt1q09zjqeetautmyzrxn9d2pu5c5glv6zcmj3qx5axrltslu90p88pqykxdv4

实际地址16进制表示:0x20 0x79 0x45 0x20 0x67 0x2b 0xef 0x17 0xb2 0x08 0x66 0x99 0x5a 0xa0 0xf2 0x98 0xa2 0x3e 0xcd 0x0b 0x1b 0x94 0x40 0x6a 0x74 0xc3 0xfa 0xe1 0xfe 0x15 0xe1 0x39 0xc2

总结:

P2PKH、P2SH:是现在所有钱包都支持的格式,应用最广。

P2WPKH、P2WSH是隔离见证的标准格式,判定简单,相对比较新,很多旧钱包没有支持,但随着隔离见证技术的应用(隔离见证优点及特性请查看相关资料,目前很火的闪电网络就应用了隔离见证技术),会有更多的钱包支持。

P2SH-P2WPKH、P2SH-P2WSH是为了支持旧钱包对P2WPKH、 P2WSH做的升值,应用此格式,旧钱包可以创建给隔离见证地址的交易, 对于P2SH-P2WPKH、P2SH-P2WSH作为输入的签名过程会更复杂一些。

由于能力有限,文中有错误的地方请指正,我将及时更正。

------------------------结束------------------------

A:计算P2PKH地址

pubkey = '04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a'
pubkey_compressed='02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c'



1、取得公钥
未压缩公钥: 04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a
压缩公钥: 02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

2、计算步骤1的sha256值
未压缩: 58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef
[vagrant@vm-node1:~]$ echo -n "04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a" | xxd -r -p | sha256sum
58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef  -

压缩: fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959
[vagrant@vm-node1:~]$ echo -n "02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c" | xxd -r -p |sha256sum
fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959  -

3、对步骤2取ripemd160运算
未压缩: a65d1a239d4ec666643d350c7bb8fc44d2881128
[vagrant@vm-node1:~]$ echo -n "58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef" | xxd -r -p | openssl  dgst -ripemd160 -provider legacy
RIPEMD-160(stdin)= a65d1a239d4ec666643d350c7bb8fc44d2881128

压缩: d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326
[vagrant@vm-node1:~]$ echo -n "fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959" | xxd -r -p | openssl  dgst -ripemd160 -provider legacy
RIPEMD-160(stdin)= d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326

4、计算checksum,首先对步骤3加版本号 (p2pkh时,主网为0x00),然后进行两次sha256计算,最后取前4个字节作为checksum
未压缩: 
1)、加0x00:  00a65d1a239d4ec666643d350c7bb8fc44d2881128
2)、第一次sha256: dd1cd208877a6a835fa0cee5095de605a7bc6f15efaa4bf977f733c35b050934
[vagrant@vm-node1:~]$ echo -n "00a65d1a239d4ec666643d350c7bb8fc44d2881128" |xxd -r -p | sha256sum
dd1cd208877a6a835fa0cee5095de605a7bc6f15efaa4bf977f733c35b050934  -

3)、第二次sha256: 268e839baa663479bad676b100524229ca219ffacd44681f472e210792b2622c
[vagrant@vm-node1:~]$ echo -n "dd1cd208877a6a835fa0cee5095de605a7bc6f15efaa4bf977f733c35b050934" |xxd -r -p | sha256sum
268e839baa663479bad676b100524229ca219ffacd44681f472e210792b2622c  -
4)、对3)步骤结果取前4个字节: 268e839b
[vagrant@vm-node1:~]$ echo -n "268e839baa663479bad676b100524229ca219ffacd44681f472e210792b2622c" | xxd -p -l 8 | xxd -r -p
268e839b

压缩: 
1)、加0x00:  00d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326
2)、第一次sha256: f337de957d25fdbc08f444879c851175ee3d59233e16365baef5a7db0a44e156
[vagrant@vm-node1:~]$ echo -n "00d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326" |xxd -r -p | sha256sum
f337de957d25fdbc08f444879c851175ee3d59233e16365baef5a7db0a44e156  -

3)、第二次sha256: 31fcaad6680f04ae1f98980d467b36f4473cbb95c0403df30034e23dc9bce3e2
[vagrant@vm-node1:~]$ echo -n "f337de957d25fdbc08f444879c851175ee3d59233e16365baef5a7db0a44e156" |xxd -r -p | sha256sum
31fcaad6680f04ae1f98980d467b36f4473cbb95c0403df30034e23dc9bce3e2  -
4)、对3)步骤结果取前4个字节:31fcaad6
[vagrant@vm-node1:~]$ echo -n "31fcaad6680f04ae1f98980d467b36f4473cbb95c0403df30034e23dc9bce3e2" | xxd -p -l 8 | xxd -r -p
31fcaad6

5、用格式 [version][ripemd160_hash][checksum] 构造出下面结果,
p2pkh地址的version=0x00,ripemd160_hash的值是步骤3的值,checksum是步骤4的结果
未压缩: 
version=0x00
ripemd160_hash=a65d1a239d4ec666643d350c7bb8fc44d2881128
checksum=268e839b
最终结果为: 00a65d1a239d4ec666643d350c7bb8fc44d2881128268e839b

压缩: 
version=0x00
ripemd160_hash=d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326
checksum=31fcaad6
最终结果为: 00d9351dcbad5b8f3b8bfa2f2cdc85c28118ca932631fcaad6


6、对上面结果进行 Base58Check 编码,
未压缩: 1GAehh7TsJAHuUAeKZcXf5CnwuGuGgyX2S
[vagrant@vm-node1:~]$ echo -n "00a65d1a239d4ec666643d350c7bb8fc44d2881128268e839b" | xxd -r -p | base58
1GAehh7TsJAHuUAeKZcXf5CnwuGuGgyX2S

压缩: 1LoVGDgRs9hTfTNJNuXKSpywcbdvwRXpmK
[vagrant@vm-node1:~]$ echo -n "00d9351dcbad5b8f3b8bfa2f2cdc85c28118ca932631fcaad6" | xxd -r -p | base58
1LoVGDgRs9hTfTNJNuXKSpywcbdvwRXpmK

最后生成的两个地址和在这个页面查到的是一致的



B、P2SH地址生成,根据这里查到的,P2SH地址主网为0x05,编码类型为base58,


P2SH: 需要用压缩公钥!!!!!!
那下面用非压缩公钥计算一下,看能计算出这个什么东西
1、取得公钥
未压缩公钥: 04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a

2、计算步骤1的sha256值
未压缩: 58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef
[vagrant@vm-node1:~]$ echo -n "04d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645cd85228a6fb29940e858e7e55842ae2bd115d1ed7cc0e82d934e929c97648cb0a" | xxd -r -p | sha256sum
58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef  -


3、对步骤2取ripemd160运算 ,这一步还和P2PKH一致
未压缩: a65d1a239d4ec666643d350c7bb8fc44d2881128
[vagrant@vm-node1:~]$ echo -n "58618fffe27f39d1f68d8d4eb5d496ab6925d1c0e981a522720495a9720552ef" | xxd -r -p | openssl  dgst -ripemd160 -provider legacy
RIPEMD-160(stdin)= a65d1a239d4ec666643d350c7bb8fc44d2881128


4、计算checksum,首先对步骤3加版本号 (P2SH时,主网为0x05),然后进行两次sha256计算,最后取前4个字节作为checksum
未压缩: 
1)、加0x00:  05a65d1a239d4ec666643d350c7bb8fc44d2881128
2)、第一次sha256: 3d70236c0f4ec01c91597b7e23d249d368175214d9d3244c6dec06397a9d392b
[vagrant@vm-node1:~]$ echo -n "05a65d1a239d4ec666643d350c7bb8fc44d2881128"  | xxd -r -p | sha256sum
3d70236c0f4ec01c91597b7e23d249d368175214d9d3244c6dec06397a9d392b  -

3)、第二次sha256: aae2d7d7ad04fa386b1c9179fedeb4979d5210029c9aac312b6e307f2d8b6a9a
[vagrant@vm-node1:~]$ echo -n "3d70236c0f4ec01c91597b7e23d249d368175214d9d3244c6dec06397a9d392b" | xxd -r -p |   sha256sum
aae2d7d7ad04fa386b1c9179fedeb4979d5210029c9aac312b6e307f2d8b6a9a  -

4)、对3)步骤结果取前4个字节:aae2d7d7
[vagrant@vm-node1:~]$ echo -n "aae2d7d7ad04fa386b1c9179fedeb4979d5210029c9aac312b6e307f2d8b6a9a" | xxd -p -l 8 | xxd -r -p
aae2d7d7


5、用格式 [version][ripemd160_hash][checksum] 构造出下面结果,
p2sh地址的version=0x05,ripemd160_hash的值是步骤3的值,checksum是步骤4的结果
未压缩: 
version=0x05
ripemd160_hash=a65d1a239d4ec666643d350c7bb8fc44d2881128
checksum=aae2d7d7
最终结果为: 05a65d1a239d4ec666643d350c7bb8fc44d2881128aae2d7d7


6、对上面结果进行 Base58Check 编码,
未压缩: 3GrfdEbuRCUfzds5SfH85hZj6RZctF5Nfg
[vagrant@vm-node1:~]$ echo -n "05a65d1a239d4ec666643d350c7bb8fc44d2881128aae2d7d7" | xxd -r -p | base58
3GrfdEbuRCUfzds5SfH85hZj6RZctF5Nfg




P2SH: 需要用压缩公钥,步骤参考: https://bitcointalk.org/index.php?topic=5229211.0
1、取得公钥
压缩公钥: 02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

2、计算步骤1的sha256值
压缩: fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959
[vagrant@vm-node1:~]$ echo -n "02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c" | xxd -r -p |sha256sum
fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959  -

3、对步骤2取ripemd160运算 
压缩: d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326
[vagrant@vm-node1:~]$ echo -n "fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959" | xxd -r -p | openssl  dgst -ripemd160 -provider legacy
RIPEMD-160(stdin)= d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326


4、Build the redeem script that is OP_0 PushData<Step_3_Result>
压缩: 
1)、加0x0014:  0014d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326


5、计算步骤4的sha256
sha256: 1ecdf8533accbb86c5d264adfa0d9af869a37386b9e8733b55bef753db486981
[vagrant@vm-node1:dev]$ echo -n "0014d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326" | xxd -r -p | sha256sum
1ecdf8533accbb86c5d264adfa0d9af869a37386b9e8733b55bef753db486981  -

6、计算步骤5的ripemd160:
ripemd160: 7db6766dce18d816eaac1198391e8bdcf70b253a
[vagrant@vm-node1:dev]$ echo -n "1ecdf8533accbb86c5d264adfa0d9af869a37386b9e8733b55bef753db486981" | xxd -r -p | openssldgst -provider legacy -ripemd160
RIPEMD-160(stdin)= 7db6766dce18d816eaac1198391e8bdcf70b253a

7、在步骤6基础上增加version和checksum,此时P2SH的version=0x05
压缩: 
version=0x05
ripemd160_hash=7db6766dce18d816eaac1198391e8bdcf70b253a
version+ripemd160=057db6766dce18d816eaac1198391e8bdcf70b253a
checksum=sha256(sha256(version+ripemd160))='b3e8e9dd'
[vagrant@vm-node1:dev]$ echo -n "057db6766dce18d816eaac1198391e8bdcf70b253a" | xxd -r -p | sha256sum  | xxd -r -p | sha256sum | xxd -p -l 8 |xxd -r -p
b3e8e9dd
最后结果为: version+ripemd160_hash+checksum
'057db6766dce18d816eaac1198391e8bdcf70b253ab3e8e9dd'


8、对上面结果进行 Base58Check 编码,
压缩: 3D9iyFHi1Zs9KoyynUfrL82rGhJfYTfSG4
[vagrant@vm-node1:dev]$ echo -n "057db6766dce18d816eaac1198391e8bdcf70b253ab3e8e9dd" | xxd -r -p | base58
3D9iyFHi1Zs9KoyynUfrL82rGhJfYTfSG4

这个是正确的!!!

后面看下P2WPKH地址如何计算!!!