gpt4 book ai didi

python - 如何在 Python 密码学中为 ECDSA (secp256k1) 生成较短的私钥

转载 作者:太空宇宙 更新时间:2023-11-03 10:50:07 29 4
gpt4 key购买 nike

我正在尝试通过关注 this guide 来学习如何创建比特币地址.如果向下滚动,第一步,即第 0 步,是拥有一个 256 位(64 十六进制)长的 ECDSA key 。我研究了 Python Cryptography 并使用下面的代码来测试生成 key ,但保存的 key 始终是一个长的(180 个字符)base 64 字符串。

我已尝试阅读文档并查看我在 Github 上调用的函数,但我看不到在哪里可以指定 key 的长度。在 this file 的第 216 行,它表示 secp256k1 的 key 大小默认为 256 位。这是否意味着我导出错误?

或者,我考虑过在 secp256k1,( 0x10xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C 范围内生成一个随机的十六进制字符串,长度为 64 个字符D036 4140 ),但我看不到在哪里可以从字符串或十六进制值创建私钥实例

gentest.py

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import load_pem_private_key


def gen_key():
private_key = ec.generate_private_key(
ec.SECP256K1(), default_backend()
)
return private_key


def save_key(pk, filename):
pem = pk.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
with open(filename, 'wb') as pem_out:
pem_out.write(pem)

def load_key(filename):
with open(filename, 'rb') as pem_in:
pemlines = pem_in.read()

private_key = load_pem_private_key(pemlines, None, default_backend())
return private_key

if __name__ == '__main__':
pk = gen_key()
filename = 'privkey.pem'
save_key(pk, filename)
pk2 = load_key(filename)

privkey.pem

-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgQGh8om7IuKSTW637ZQug
SZQHUTv/yQzmM+KxGi1bg0ehRANCAATALLpDeKtfHxEnrgazJUu2z2/esSfzF5bj
Z4B/IBBB9uYHyMtjY8hS926bpXiWql7y7MMZXDSDD/zYWELuJZ1U
-----END PRIVATE KEY-----

最佳答案

如果您没有不透明 私钥(我认为这涉及专业硬件,所以不太可能),您可以通过key.private_numbers() method 访问私有(private)号码信息。私钥对象的,此时您可以将值本身作为整数访问; .private_numbers() 方法生成一个 EllipticCurvePrivateNumbers带有 .private_value attribute 的对象,一个 Python int。使用 format() 将该值格式化为 64 个字符的零填充十六进制:

>>> key = gen_key()
>>> key.private_numbers()
<cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateNumbers object at 0x110a6b828>
>>> key.private_numbers().private_value
1704732612341385685752055250212403073347894734334856205449544619169914419683
>>> format(key.private_numbers().private_value, '064x')
'03c4d82ee8e4c9d245f5a5ceae513569fb5693a0c3cca223b198c6944521f9e3'

或者使用 int.to_bytes() 将其编码为字节按大端或小端顺序(整数十六进制输出按大端顺序):

>>> key.private_numbers().private_value.to_bytes(32, 'big')
b'\x03\xc4\xd8.\xe8\xe4\xc9\xd2E\xf5\xa5\xce\xaeQ5i\xfbV\x93\xa0\xc3\xcc\xa2#\xb1\x98\xc6\x94E!\xf9\xe3'
>>> key.private_numbers().private_value.to_bytes(32, 'big').hex()
'03c4d82ee8e4c9d245f5a5ceae513569fb5693a0c3cca223b198c6944521f9e3'

所有这一切都有点令人费解,因为操作 cryptography 模块通常不需要它,该模块通过数据结构与 OpenSSL 或其他密码学后端一起工作,这些数据结构将这些信息保存在库友好的环境中,而不是 Python-友好的格式。

是的,您生成的 key 长 256 位,您可以通过查看私钥的 .key_size 属性来验证这一点:

>>> key.key_size
256

DER 格式可能是另一条路径,因为那是机器可读的信息。传统的 OpenSSL 格式使得从 X.690 ASN.1 structure 中获取信息相对容易。手动,无需安装 ASN.1 解析器,但这并不是万无一失的。您将查找 04 20 字节序列(4 是一个八位字节字符串,20 十六进制表示它的长度为 32 个字节), 该值将是第一个整数的序列;这意味着私钥将始终从第 8 个字节开始:

der_bytes = key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption())
assert der_bytes[5:7] == b'\x04\x20'
key_bytes = der_bytes[7:39]

不过,我不能 100% 确定这些断言是否成立,只是访问私有(private)号码要简单得多。

关于python - 如何在 Python 密码学中为 ECDSA (secp256k1) 生成较短的私钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52236189/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com