【比特币】地址生成
来源:互联网 发布:淘宝网防晒衣女 编辑:程序博客网 时间:2024/05/15 23:45
1) 带校验以及前导0的base58编码方法源代码
#include <stdio.h>#include <stdlib.h>#include <string>#include <openssl/bn.h>#define DOMAIN_CHECK(c) ('0'<=(c)&&(c)<='9'||'a'<=(c)&&(c)<='f'||'A'<=(c)&&(c)<='F')#define BASE58TABLE "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"std::string base58encode(const std::string & hexstring){ std::string result = ""; BN_CTX * bnctx = BN_CTX_new(); BN_CTX_init(bnctx); BIGNUM * bn = BN_new(); BIGNUM * bn0= BN_new(); BIGNUM * bn58=BN_new(); BIGNUM * dv = BN_new(); BIGNUM * rem= BN_new(); BN_init(bn); BN_init(bn0); BN_init(bn58); BN_init(dv); BN_init(rem); BN_hex2bn(&bn, hexstring.c_str()); BN_hex2bn(&bn58, "3a");//58 BN_hex2bn(&bn0,"0"); while(BN_cmp(bn, bn0)>0){ BN_div(dv, rem, bn, bn58, bnctx); BN_copy(bn, dv); char base58char = BASE58TABLE[BN_get_word(rem)]; result += base58char; } // compute leading-zeros and prepend '1' (base58table[0]) const char * phexstr = hexstring.c_str(); int hexlen = hexstring.length(); for (int i = 1; i < hexlen; i += 2) { if (phexstr[i-1] == '0' && phexstr[i] == '0') result += BASE58TABLE[0]; else break; } // little endian -> big endian // most significant byte (the dv) is calulated at the end, // and appended at the end of string. // so convert it to big endian. std::string::iterator pbegin = result.begin(); std::string::iterator pend = result.end(); while(pbegin < pend) { char c = *pbegin; *(pbegin++) = *(--pend); *pend = c; } return result;}int main(int argc, char * argv []){ std::string hexstring = ""; FILE * fin = stdin; while(!feof(fin)) { char c = fgetc(fin); if (DOMAIN_CHECK(c)) hexstring +=c; } // check empty if (hexstring.length() == 0) return -1; // assert length %2 == 0 if (hexstring.length() % 2) hexstring.insert(hexstring.begin(), '0'); fprintf(stdout, "%s", base58encode(hexstring).c_str()); return 0;}
比特币地址是ECDSA算法的公钥
关于这个算法的三个特性:
1)私钥可以推导出公钥,但是公钥无法推导出私钥,
2)公钥有2个表示方式,压缩方式,前导为0x02,0x03;非压缩方式,前导为0x04
3)私钥对一个hash签名的结果是一个整数对(r,s),公钥可以验证是否有对应的私钥签发
1) 计算这个公钥对应的地址,
0400112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
echo -n 0400112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff | h2b | sha256sum | sed -e 's/ -//g' | h2b | openssl dgst -ripemd160
(stdin)= 77eaeaabc6da57ece603d2b56e4d21c865d5a5cd
再跳到下面的第2步,使用带hash-checking的base58编码
2) 如何从一个地址对象生成打印一个比特币地址出来。
关于CBitcoinAddress的定义:
保存vchVersion字段和vchData字段(20个字节长度,ripemd160的hash结果),分别表示《版本号》和《RipeMD160表示的ID》内容。
版本号,可以是 0x00和0x05两种,但是base58编码在比特币系统中的应用还有其他几种类型,参考wiki
主要有几个步骤:
2.1,序列化
【版本】+【Ripemd160数据部分】
插播:至于怎么从公钥得到RipmeMd160的结果可以参考wiki,先sha256sum再ripemd160就可以了。
举例:
假如从公钥hash出来的id是1122334455667788990011223344556677889900,
05+1122334455667788990011223344556677889900 => 051122334455667788990011223344556677889900
2.2,计算校验和
HASH(ResultStep1)即:Hash256(Hash256(051122334455667788990011223344556677889900)) => 68787bf6caca67526183fdfb06d9a3efc0f2264cdfe94af017e5428d83ddf873
这是一个LE表示的uint256整数,提取前面的4个字节
得到:68787bf6
2.3, 追加第二步的校验和到第一步的结果后面再进行base58编码
Base58(05112233445566778899001122334455667788990068787bf6) 也就是对一个(1+20+4)总共25个元素表示的大整数进行base58编码,这个整数肯定小于32字节的uint256。
得到: 33FcP5di8njrEcWNRvHhjx46fa2jrWPzYD
备注:
1)这个过程是可以反向解码校验的。
2)Hash256计算的对象都是256字节的大整数(小端表示的字节数据,博客中和wiki中都是用16进制表示的,要么用bignum库反序列化得到大整数,或者使用十六进制字符串反序列化 得到字节数组以后再计算)
3)举例的输入是随意的,实际0x05版本的比特币地址(也就是3前导的)是脚本地址,而不是公钥地址。
4)一个脚本实现的从CPubKeyID生成比特币地址
hex2bvec.sh 转换16进制字符串到字节数组
echo -n -e $(echo -n $(cat) | sed -e 's/\([a-fA-F0-9]\{2\}\)/\\x\1/g' )
pubkey2addr.sh
echo -n 00$1$(echo -n 00$1 | hex2bvec.sh | sha256sum | sed -e 's/ -//g' | hex2bvec.sh | sha256sum | sed -e 's/\([0-9a-fA-F]\{8\}\).*/\1/g') | base58
把比特币发送到某个地址,使用的是keyid,未经base58编码的公钥id,40个字节十六进制表示的20字节整数。
Output Scripts
OP_DUP OP_HASH160 c83dc3af1091303168fd1ab44e528d7c941ab49c OP_EQUALVERIFY OP_CHECKSIG OKOP_DUP OP_HASH160 45d906fdc235c3ffb40acb4831a509e5bac4092c OP_EQUALVERIFY OP_CHECKSIGsh pubkey2addr.sh c83dc3af1091303168fd1ab44e528d7c941ab49c 得到地址1KFn8qCwsNwo5fSC3qMHs6d3FEPTsojhKysh pubkey2addr.sh 45d906fdc235c3ffb40acb4831a509e5bac4092c 得到地址17NKcZNXqAbxWsTwB1UJHjc9mQG3yjGALA
也可以修改一个script2addr.sh
echo -n 00$1$(echo -n 00$1 | hex2bvec.sh | sha256sum | sed -e 's/ -//g' | hex2bvec.sh | sha256sum | sed -e 's/\([0-9a-fA-F]\{8\}\).*/\1/g') | base58
参考网页
- 【比特币】地址生成
- 比特币地址生成(图形化)****
- 比特币钱包地址生成算法
- 比特币地址的生成算法是怎样的?
- 利用vanitygen生成比特币个性地址的教程
- 比特币地址
- 比特币github地址
- 比特币github地址
- 比特币钱包地址
- 比特币学习之比特币地址
- 初识比特币——比特币地址
- 比特币地址格式是怎样的?
- 如何简单的获取比特币地址?
- 【比特币】椭圆曲线密钥生成
- 如何用百家姓表示比特币收款地址
- 椭圆曲线公钥转换为比特币地址原理
- 我的比特币地址 my bitcoin address
- 比特币开发专题(区块链内核密钥、地址、钱包)
- [leetcode] Convert Sorted Array to Binary Search Tree
- 静态链接
- 2014-07-15 lamp编译安装搞定
- rrrrrr
- owncloud将data目录配置为HDFS上
- 【比特币】地址生成
- imagick获取图片尺寸有bug
- native2ascii.exe的使用
- 护眼色备份
- 前端
- poj 1142 筛质数(查找Smith数)
- Android 文字环绕 图文混排 支持Span折叠
- 查看电脑的信息
- 判断Android ViewPager滑动到最后一页