是否有带有点压缩的公钥初始化 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&lt; ECP &gt;DL_GroupParameters_EC&lt; EC2M &gt;),然后调用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 客户端配置

初始化单例异步 iOS

RSACryptoServiceProvider 用自己的公钥和私钥初始化

TypeScript是否支持带有对象初始值设定项的构造函数?

如何从发件人那里恢复压缩的 y 值?

“gpg:无法检查签名:没有公钥”从代码极光初始化回购