是否有带有点压缩的公钥初始化 API?
Posted
技术标签:
【中文标题】是否有带有点压缩的公钥初始化 API?【英文标题】:Is there public key initialization API with point compression? 【发布时间】:2014-01-15 03:05:12 【问题描述】:我在 CryptoPP 上翻来覆去,找不到这个特定问题的答案。这是示例源代码(部分)
AutoSeededRandomPool prng;
//Generate a private key
ECDSA<ECP, CryptoPP::SHA256>::PrivateKey privateKey;
privateKey.Initialize(prng, CryptoPP::ASN1::secp256r1());
// Generate publicKey
ECDSA<ECP, CryptoPP::SHA256>::PublicKey publicKey;
privateKey.MakePublicKey(publicKey);
// Extract Component values
Integer p = privateKey.GetGroupParameters().GetCurve().GetField().GetModulus();
Integer a = privateKey.GetGroupParameters().GetCurve().GetA();
Integer b = privateKey.GetGroupParameters().GetCurve().GetB();
Integer Gx = privateKey.GetGroupParameters().GetSubgroupGenerator().x;
Integer Gy = privateKey.GetGroupParameters().GetSubgroupGenerator().y;
Integer n = privateKey.GetGroupParameters().GetSubgroupOrder();
Integer h = privateKey.GetGroupParameters().GetCofactor();
Integer Qx = publicKey.GetPublicElement().x;
Integer Qy = publicKey.GetPublicElement().y;
Integer x = privateKey.GetPrivateExponent();
// Construct Point elelemt;
ECP curve(p,a,b);
ECP::Point G(Gx,Gy);
ECP::Point Q(Qx,Qy);
//Build publicKey using elements (no point compression)
ECDSA<ECP, CryptoPP::SHA256>::PublicKey GeneratedPublicKey;
GeneratedPublicKey.Initialize(curve,G,n,Q);
assert(GeneratedPublicKey.Validate(prng, 3));
//Build publicKey using elements (with point compression)?
通过这种方式,我可以使用组件值生成 publicKey。然而,我不能 使它与点压缩一起工作——这意味着我没有 Qy 值——有没有 怎么做? Initialize 方法有两个重载,但都不是针对点的 压缩情况。
我的问题是关于“PublicKey.Initialize(curve,G,n,Q)”的 Crypto++。由于我不能用我当前的项目转移整个 publicKey - 我不得不指定域 参数作为索引值,只能传递 Qx 值。所以我应该初始化 publicKey 使用类似“PublicKey.Initialize(curve,G,n,Q)”的东西但是,我找不到关于点压缩的初始化 API。
所以,这不是关于“如何进行点压缩”而是“有没有办法初始化 没有 Qy 值的公钥?”
【问题讨论】:
准确告诉我们您拥有什么。您从未在//Build publicKey using elements (with point compression)?
处告诉过您正在使用的参数。如果它是 ASN.1 编码值,请使用 dumpasn1
向我们展示。如果原始形式是二进制,则显示给我们十六进制编码。
【参考方案1】:
如何仅使用 x 值(点压缩)构造 ECDSA 公钥?
x
是私有指数。公钥是曲线上的一个点;并且它不使用私有指数。
获取公钥:取私有指数,然后将基点提高到它。即Q = G^x
。
如果您想在私钥或解密器上设置私钥,请设置域参数(即DL_GroupParameters_EC< ECP >
或DL_GroupParameters_EC< EC2M >
),然后调用SetPrivateExponent(x);
。
您在How can I recover compressed y value from sender? 上查看过您之前的问题吗?社区花时间为您提供答案和示例代码,但您没有确认或跟进。
我认为owlstead说得最好here:
如果您不愿意接受答案,我们为什么会关心回答您? 甚至跟进他们?你的问题都很好,但是方法 你对待社区很糟糕。
【讨论】:
我确实阅读了您对我之前的回答的回答,这对我帮助很大。再次感谢你:) 如果这个问题看起来像我忽略了您对我之前问题的回答,我深表歉意。不是,我确实从您之前的回答中学到了很多东西,现在我可以进行点压缩了。这对我来说是一个不同的问题。【参考方案2】:“有没有办法在没有 Qy 值的情况下初始化公钥?”
是的,有。这是一个加密++示例:
#include <string>
#include <iostream>
#include <cryptopp/cryptlib.h>
#include <cryptopp/ecp.h>
#include <cryptopp/eccrypto.h>
#include <cryptopp/hex.h>
#include <cryptopp/oids.h>
#include <cryptopp/osrng.h>
using namespace CryptoPP;
using std::cout;
using std::endl;
int main()
OID curve = ASN1::secp256r1();
ECDH<ECP>::Domain domain(curve);
SecByteBlock privKey(domain.PrivateKeyLength());
SecByteBlock pubKey(domain.PublicKeyLength());
AutoSeededRandomPool prng;
domain.GenerateKeyPair(prng, privKey, pubKey);
// Convert public key to string representation
std::string pub_str;
HexEncoder encoder;
encoder.Attach( new StringSink(pub_str) );
encoder.Put( pubKey.data(), pubKey.size() );
encoder.MessageEnd();
// Uncompressed point - first byte '04' in front of the string.
std::cout << "Uncompressed public key (point) " << pub_str << endl;
// Extract x value from the point
std::string public_point_x = pub_str.substr(2, 64);
// Compressed - '02' byte in front of the string.
public_point_x = "02" + public_point_x;
std::cout << "Compressed public key (point) " << public_point_x << endl;
// ----- reconstruct point from compressed point/value.
StringSource ss(public_point_x, true, new HexDecoder);
ECP::Point point;
domain.GetGroupParameters().GetCurve().DecodePoint(point, ss, ss.MaxRetrievable());
cout << "Result after decompression X: " << std::hex << point.x << endl;
cout << "Result after decompression Y: " << std::hex << point.y << endl;
return 0;
我希望这是您问题的答案。我使用的是 ECDH,但它应该同样适用于 ECDSA 类。
【讨论】:
以上是关于是否有带有点压缩的公钥初始化 API?的主要内容,如果未能解决你的问题,请参考以下文章
Android Retrofit 更新 HTTP 客户端配置
RSACryptoServiceProvider 用自己的公钥和私钥初始化