c++以太坊访问:账户私钥 、公钥、地址的生成(四)

c++以太坊访问:账户私钥 、公钥、地址的生成(四)先理解以太坊的私钥 公钥 地址指的什么意思 私钥 一组 64 位的 16 进制字符 256 位的随机数 32 字节 用于发送以太的交易中创建签名来证明自己对资金的所有权 公钥 私钥通过椭圆曲线加密 secp256k1 算法单向生成的 512 位 64 字节 数

大家好,我是讯享网,很高兴认识大家。

先理解以太坊的私钥、公钥、地址指的什么意思。

私钥:一组64位的16进制字符,256位的随机数(32字节),用于发送以太的交易中创建签名来证明自己对资金的所有权。

公钥:私钥通过椭圆曲线加密secp256k1算法单向生成的512位 (64字节)数。

以太坊地址:由未压缩公钥的 Keccak-256 单向哈希(现在成为sha3_256),取最后20个字节(40位)派生出来的标识符。

生成流程:

①私钥 (private key)

  伪随机数(或者secp256k1椭圆曲线算法)产生的256bit私钥示例(256bit  16进制32字节)

  ee1ff0b356b996fb1dbd54bb3f2d31b43cbbc07e8f727d8780eed1d09e

②公钥 (public key)

  1. 采用椭圆曲线数字签名算法ECDSA-secp256k1将私钥(32字节)映射成公钥(65字节)(前缀04+Y公钥+X公钥):

       X(9ffb11904aa5fdb20d58b3e86474fffcc58b560a18ae4c3170f05b5162c15f37)

       2. 拿公钥(非压缩公钥)来hash,计算公钥的 Sha3_256 哈希值(32bytes):

  263DE9A0EC149B5B91EAB81121EE45103EE1FDD1A6D89385FAA4283E0C

       注意:经过测试,非压缩公钥需要除去前缀04,并且转换为字节字符串,进行sha3_256哈希,才能得到正确的hash值匹配地址


讯享网

       3. 取上一步结果取后20bytes即以太坊地址:

  21EE45103EE1FDD1A6D89385FAA4283E0C

③地址 (address)

  0x21EE45103EE1FDD1A6D89385FAA4283E0C

最主要的还是libsecp256k1椭圆曲线算法原理,在这里就不做多的讲解:

请参考比特币官网对secp256k1的介绍:https://en.bitcoin.it/wiki/Secp256k1   

原理看完后也许还是不清楚如何转换成代码来进行操作,刚好网上是有libsecp256k1库的需要自己进行编译。无论是比特币还是以太坊或者web3j底层内部其实都是调用libsecp256k1库来进行封装使用的。因此只需要会使用libsecp256k1库的接口,问题不大。

libsecp256k1库:https://github.com/bitcoin-core/secp256k1

代码流程:

string EthSignature::getETHAddress(string privatekey) { char prikeyhex[65]; strcpy(prikeyhex,(char*)(privatekey.data())); int len = sizeof(prikeyhex) / 2; // 私钥长度 - 32字节 unsigned char prikey[len]; // 私钥存储 int ii; // 索引值 int ret; // 返回值 unsigned char CPubKey[65]; // 公钥存储 size_t clen; // 返回公钥长度 secp256k1_context *secp256k1_context_sign; secp256k1_pubkey pubkey; // secp256k1返回公钥 // 将私钥字符串转换为字节存储 for(ii = 0; ii < sizeof(prikeyhex); ii+=2){ prikey[ii/2] = hex2int(prikeyhex[ii]) * 16 + hex2int(prikeyhex[ii + 1]); } // 打印私钥 printf("Private key: "); for(ii = 0; ii < len; ii++) { printf("%02x",prikey[ii]); } printf("\n"); // 生成公钥 secp256k1_context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, prikey); char data[131]; int offset = 0; // 打印公钥 if(ret){ printf("Public key : "); printf("[X("); for(ii = 63; ii >= 32; ii--){ printf("%02x", pubkey.data[ii]); } printf("):Y("); for(ii = 31; ii >= 0; ii--){ printf("%02x", pubkey.data[ii]); } printf(")]\n"); // 获取压缩公钥 clen = 65; secp256k1_ec_pubkey_serialize(secp256k1_context_sign, CPubKey, &clen, &pubkey, SECP256K1_EC_COMPRESSED); printf("Compressed key : "); for(ii = 0; ii < clen; ii++){ printf("%02x", CPubKey[ii]); } printf("\n"); // 获取非压缩公钥 clen = 65; secp256k1_ec_pubkey_serialize(secp256k1_context_sign, CPubKey, &clen, &pubkey, SECP256K1_EC_UNCOMPRESSED); printf("Uncompressed key: "); for(ii = 0; ii < clen; ii++){ offset += sprintf(data+offset,"%02x", CPubKey[ii]); } data[offset] = '\0'; printf("\n"); } if (secp256k1_context_sign) { secp256k1_context_destroy(secp256k1_context_sign); } //(前缀04+X公钥+Y公钥) //公钥(非压缩公钥)来hash,转换为字符串,计算公钥的 Keccak-256 哈希值(32bytes) string da(data); string cc = m_pOperation->hexStringToString(da.substr(2),128,""); string str=sha3_256(cc); string address = "0x"+str.substr(str.size()-40); return address; }

讯享网

参考:

https://www.cnblogs.com/kumata/p/10591394.html

https://www.cnblogs.com/wanghui-garcia/p/9646508.html

小讯
上一篇 2025-01-26 09:17
下一篇 2025-02-08 18:38

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/39715.html