我正在使用 Ruby 2.5.x OpenSSL 库尝试椭圆曲线。我可以使用
轻松生成私钥和公钥对curve = OpenSSL::PKey::EC.new('secp256k1')
curve.generate_key
但是给定私钥我想重新生成公钥。
我知道 OpenSSL 可以做到这一点,因为命令行允许你做到这一点,Ruby 比特币项目也可以做到这一点。但 Ruby Bitcoin 项目有自己的使用 FFI 的 OpenSSL 接口,而不是 Ruby 提供的接口。
Ruby 2.5.x openssl 库是否没有公开足够的 OpenSSL 接口来从私钥生成椭圆曲线公钥,或者它可以但没有记录?
如果有人也有兴趣获取 pem 格式的公钥:)
example_key = OpenSSL::PKey::EC.new('secp256k1').generate_key
puts example_key.to_pem
pkey = OpenSSL::PKey::EC.new(example_key.public_key.group)
pkey.public_key = example_key.public_key
puts pkey.to_pem
https://stackoverflow.com/a/64023608/2603673中的答案不适用于openssl 3.x,因为密钥现在是不可变的,我们需要更改为:
key = OpenSSL::PKey::EC.new('secp256k1').generate_key
group = key.public_key.group
point = key.public_key
asn1 = OpenSSL::ASN1::Sequence(
[
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId('id-ecPublicKey'),
OpenSSL::ASN1::ObjectId(group.curve_name)
]),
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
]
)
pkey = OpenSSL::PKey::EC.new(asn1.to_der)
puts pkey.to_pem
据我所知,Ruby OpenSSL 绑定不允许您直接从
PKey::EC
对象获取公钥,但它们确实暴露了足够的信息来让您自己进行计算,这很简单。
将私钥作为
OpenSSL:BN
对象给出,对于示例,我们可以这样生成:
example_key = OpenSSL::PKey::EC.new('secp256k1').generate_key
private_key = example_key.private_key
我们可以通过将组基点(即生成器)乘以私钥来计算公钥:
group = OpenSSL::PKey::EC::Group.new('secp256k1')
public_key = group.generator.mul(private_key)
公钥是
OpenSSL::PKey::EC::Point
。你可以和原版比较一下,发现是一样的:
puts example_key.public_key == public_key # => true
在 OpenSSL 3.0 中,密钥是不可变的,这意味着您无法在创建现有 OpenSSL::PKey::EC 对象后对其进行修改。您应该使用 ASN.1 编码构建公钥,而不是尝试在现有对象上设置公钥。
以下是如何重构代码以使用 OpenSSL 3.0:
private_key = OpenSSL::PKey::EC.generate("secp256k1")
asn1 = OpenSSL::ASN1::Sequence(
[
OpenSSL::ASN1::Sequence(
[
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
OpenSSL::ASN1::ObjectId(private_key.public_key.group.curve_name)
]
),
OpenSSL::ASN1::BitString(private_key.public_key.to_octet_string(:uncompressed))
]
)
public_key = OpenSSL::PKey::EC.new(asn1.to_der)
puts public_key.to_pem