从私钥生成以太坊地址 Python

文章详细介绍了如何从公钥生成以太坊地址,包括椭圆曲线公钥的生成、使用Python代码示例,以及使用掷硬币或骰子生成私钥的方法。同时,文章还深入探讨了secp256k1曲线的数学原理。

从公钥生成以太坊地址

以太坊地址是公钥的 keccack256 的最后 20 字节。公钥算法是 secp256k1,与比特币中使用的相同。

由于这是一个椭圆曲线算法,公钥是一个 (x, y) 坐标对,对应于椭圆曲线上的一个点。

生成椭圆曲线公钥

公钥是 x 和 y 的连接,这是我们对其进行哈希的对象。

代码如下所示。

from ecpy.curves import Curve
from ecpy.keys import ECPublicKey, ECPrivateKey
from sha3 import keccak_256

private_key = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

cv = Curve.get_curve('secp256k1')
pv_key = ECPrivateKey(private_key, cv)
pu_key = pv_key.get_public_key()

## 说明的等效替代:
## concat_x_y = bytes.fromhex(hex(pu_key.W.x)[2:] + hex(pu_key.W.y)[2:])

concat_x_y = pu_key.W.x.to_bytes(32, byteorder='big') + pu_key.W.y.to_bytes(32, byteorder='big')
eth_addr = '0x' + keccak_256(concat_x_y).digest()[-20:].hex()

print('private key: ', hex(private_key))
print('eth_address: ', eth_addr)

ecpy 库在这里 <https://github.com/cslashm/ECPy>。这个库在 Python 中实现了椭圆曲线数学,因此它的速度不会像围绕比特币 C 实现的封装那样快,而比特币 C 实现是由 coincurve 库使用的。

然而,Python 实现允许你逐步查看用于推导公钥的椭圆曲线数学。

你可以使用此代码通过暴力破解生成一个以太坊虚假地址,但要注意,如果你的随机性来源不安全或随机性位数太少,你可能会成为类似于 这个 的攻击的受害者。

使用 Python 和抛骰子生成私钥

你可以通过抛掷硬币 256 次自行生成以太坊地址,如果是正面则在字符串上写 1,如果是反面则写 0。

假设你得到了以下结果

result = b'1100001011001101010001001100101000001111101101111011001000110001101100011101101011010001011000101111100110010101001001101110111011001000100001010101111100001100100110010010111110110100000010011111100000110101001110000101100101011111001101010001100001000'

你可以使用以下 Python 代码将其转换为私钥

## 2 表示二进制的基数 2

private_key = hex(int(result, 2)) 

## 私钥是 0x1859a89941f6f646363b5a2c5f32a4ddd910abe19325f6813f06a70b2be6a308

然后,将该私钥插入上面部分的代码中,你就用自己的随机性生成了地址。

要更快地达到相同的效果,可以掷出一个 16 面骰子 64 次,并逐字符写出所产生的十六进制字符串。要注意的是,大多数骰子都没有表示数字零的选项,因此你需要从每个结果中减去 1。

如果你只有传统的六面骰子,则可以编写一个基数为 6 的字符串(不要忘记从每次掷骰中减去 1),并进行二进制的基数转换。你需要不断掷骰,直到你获得至少 256 位的私钥。如果你对随机性特别担心,可以使用赌场级的骰子。

使用 Python 的内置随机数库时要小心。它并非旨在提供加密安全性。如果你对该主题不熟悉,我们建议你熟悉 加密安全随机性

一般来说,你无法通过此方法初始化硬件钱包,因为他们使用的 24 个单词恢复短语与用于签名交易的私钥并不相同。24 个单词的恢复短语用于推导多种不同类型加密货币的私钥,这些加密货币由钱包持有。

数学:关于 secp256k1:从私钥生成公钥

曲线的形状

Secp256k1 定义了椭圆曲线 y2=x3+7 (mod p) 的形状,其中 p 是质数 115792089237316195423570985008687907853269984665640564039457584007908834671663

或者 2256–232–977

质数 p 不应与曲线的 混淆。并不是所有的值 0<n<p 都满足上述方程。然而,在此曲线上的操作可以保证是 封闭的。也就是说,如果两个有效点相加或相乘,结果将是在曲线上的有效数。

起始点

另一个在 secp256k1 中重要的参数是起始点 G。由于 G 是椭圆曲线上的一点,它是二维的,具有以下参数:

x = 55066263022277343669578718895168534326250603453777594175500187360389116729240

y = 32670510020758816978083085130507043184471273380659243275938904335757337482424

为了验证 G 是否是有效点,我们可以将这些数字代入 Python 中

x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663

assert pow(y, 2, p) == (pow(x, 3) + 7) % p

要创建公钥/私钥对,会生成一个随机数 s(这是私钥)。点 G 加到自身 s 次,新点 (x, y) 就是公钥。如果 s 足够大,则从 G 和 (x, y) 推导 s 是不可行的。

在此方案中,签名消息的过程归结为证明你知道 s 而不揭示它。

将 G 加到自身 s 次等同于乘以 s * G。实际上,我们可以通过剥离库存库所提供的一些抽象来在更低的层面查看这个操作。

from ecpy.curves import Curve
from sha3 import keccak_256

private_key = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

cv     = Curve.get_curve('secp256k1')
pu_key = private_key * cv.generator # 只是将私钥乘以生成点(椭圆曲线乘法)

concat_x_y = pu_key.x.to_bytes(32, byteorder='big') + pu_key.y.to_bytes(32, byteorder='big')
eth_addr = '0x' + keccak_256(concat_x_y).digest()[-20:].hex()

print('private key: ', hex(private_key))
print('eth_address: ', eth_addr)

公钥只不过是将私钥乘以 secp256k1 椭圆曲线上的点 G。就这些。

了解更多

请查看我们先进的 区块链训练营,今天就成为一个了解其他程序员不了解的核心知识的区块链开发者。

最初发表于 2023 年 1 月 30 日

  • 原文链接: rareskills.io/post/gener...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
RareSkills
RareSkills
https://www.rareskills.io/