问题描述
我不是密码学家,但我需要在项目中实施 ECDSA。我选择了 Crypto++ 来嵌入到我的 C++ 项目中。 问题是:我需要一个密钥对生成器,它在 secp256k1 曲线上生成两个十六进制压缩私钥及其相关公钥。 (32 字节私有和 33 字节公共) 这是部分工作的代码。 我确信这不是生成公钥的正确方法,尤其是将“02”或“03”作为前缀。 有谁能够帮我? 非常感谢每一种帮助。
#include <random>
#include <vector>
#include <sstream>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <cryptopp/aes.h>
#include "cryptopp/eccrypto.h"
#include "cryptopp/integer.h"
#include "cryptopp/oids.h"
#include "cryptopp/osrng.h"
#include "cryptopp/pssr.h"
#include <cryptopp/rsa.h>
#include <cryptopp/sha.h>
#include "cryptopp/cryptlib.h"
#include <cryptopp/sha3.h>
#include <cryptopp/hex.h>
#include <cryptopp/files.h>
#include <cryptopp/filters.h>
#include <cryptopp/base64.h>
#include <cryptopp/modes.h>
std::tuple<
bool,CryptoPP::ECDSA<CryptoPP::ECP,CryptoPP::SHA256>::PrivateKey,std::string> ECDSAgeneratePrivateKey()
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
ECDSA<ECP,SHA256>::PrivateKey privateKey;
privateKey.Initialize(prng,CryptoPP::ASN1::secp256k1());
if (!privateKey.Validate( prng,3 ))
return {false,privateKey,""};
const Integer& x = privateKey.GetPrivateExponent();
std::stringstream ss;
ss << std::hex << x;
std::string private_key_hex = ss.str();//.substr(1,64);
private_key_hex = private_key_hex.substr(0,64);
return {true,private_key_hex};
}
std::tuple<
bool,CryptoPP::SHA256>::PublicKey,std::string> ECDSAgeneratePublicKey(
CryptoPP::ECDSA<CryptoPP::ECP,CryptoPP::SHA256>::ECDSA::PrivateKey& privateKey)
{
using namespace CryptoPP;
CryptoPP::AutoSeededRandomPool prng;
ECDSA<ECP,SHA256>::PublicKey publicKey;
// Sanity check
if ( !privateKey.Validate(prng,3) )
return {false,publicKey,""} ;
privateKey.MakePublicKey(publicKey);
bool result = publicKey.Validate(prng,3);
if ( !result )
return {false,""};
const ECP::Point& q = publicKey.GetPublicElement();
const Integer& qx = q.x;
const Integer& qy = q.y;
std::stringstream ss_x;
ss_x << std::hex << qx;
std::string public_key_x = ss_x.str();
public_key_x = public_key_x.substr(0,64);
std::stringstream ss_y;
ss_y << std::hex << qy;
std::string public_key_y = ss_y.str();
public_key_y = public_key_y.substr(0,64);
return { true,public_key_x};
}
std::tuple<bool,CryptoPP::SHA256>::PrivateKey> ECDSAimportHexPrivateKey(const std::string& exp_)
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
ECDSA<ECP,SHA256>::PrivateKey privateKey;
std::string exp = exp_;
exp.insert(0,"0x");
Integer x(exp.c_str());
privateKey.Initialize(ASN1::secp256k1(),x);
bool result = privateKey.Validate(prng,3);
return {result,privateKey};
}
std::tuple<bool,std::string,std::string> ECDSAsignMessage(
const std::string& private_key,const std::string& message)
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
auto [private_status,regenerated_private_key] = ECDSAimportHexPrivateKey(private_key);
if (!private_status)
return {false,"",""};
ECDSA<ECP,SHA256>::Signer signer(regenerated_private_key);
size_t siglen = signer.MaxSignatureLength();
std::string signature(siglen,0x00);
siglen = signer.SignMessage( prng,(const byte*)&message[0],message.size(),(byte*)&signature[0] );
signature.resize(siglen);
std::string signature_hex;
StringSource s( signature,true /*pump all*/,new HexEncoder(new StringSink( signature_hex ),false)
); // StringSource
return {true,signature_hex,signature};
}
std::tuple<bool,CryptoPP::SHA256>::PublicKey> ECDSAimportHexPublicKey(const std::string& compact_point)
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
// ----- reconstruct point from compressed point/value.
ECDSA<ECP,SHA256>::PublicKey pubKey;
pubKey.AccessGroupParameters().Initialize(ASN1::secp256k1());
StringSource ss (compact_point,true,new CryptoPP::HexDecoder);
ECP::Point point;
pubKey.GetGroupParameters().GetCurve().DecodePoint (point,ss,ss.MaxRetrievable());
ECDSA<ECP,SHA256>::PublicKey publicKeyRegen;
publicKeyRegen.Initialize(ASN1::secp256k1(),point);
bool result = publicKeyRegen.Validate(prng,3);
if (result)
{
return {true,publicKeyRegen};
}
else
{
return {false,publicKeyRegen};
}
}
bool ECDSAVerifysignature(
const std::string& public_key,const std::string& message,const std::string& signature_hex)
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
auto[pub_status,regenerated_public_key] = ECDSAimportHexPublicKey(public_key);
if (!pub_status)
return false;
std::string signature;
StringSource s2(signature_hex,new HexDecoder(new StringSink(signature))
); // StringSource
ECDSA<ECP,SHA256>::Verifier verifier(regenerated_public_key);
bool result = verifier.VerifyMessage( (const byte*)&message[0],(const byte*)&signature[0],signature.size() );
// Verification failure?
return true; // FIXME: ASAP
return result;
}
std::tuple<bool,std::string> ECDSAGenerateKeyPair()
{
using namespace CryptoPP;
using CryptoPP::AES;
using CryptoPP::ECDSA;
using CryptoPP::ECP;
using CryptoPP::DL_GroupParameters_EC;
using CryptoPP::OID;
AutoSeededRandomPool prng;
auto[private_creation_status,private_key,private_key_string] = ECDSAgeneratePrivateKey();
if (!private_creation_status)
{
std::cout << std::endl << "Failed on create private key";
return {false,""};
}
auto[public_creation_status,public_key,public_key_string] = ECDSAgeneratePublicKey(private_key);
// sign a message& verify
std::string message = "Imagine all the people living life in peace";
auto[signatureStatus,signatureAsc] = ECDSAsignMessage(private_key_string,message);
if (!signatureStatus)
{
std::cout << std::endl << "Failed on Sign message";
return {false,""};
}
// this public_key is not complete,in order to being a 33 byte public key we have to add "02" or "03" as a prefix depends on being odd or even!
// since I didn't find how to figure out odd or even,I try one by 02 and if it failed by 03
// I know it is the ugliest solution in the world :(
bool signatureVerifyStatus = ECDSAVerifysignature("02" + public_key_string,message,signature_hex);
if (signatureVerifyStatus)
{
public_key_string = "02" + public_key_string; //FIXME ASAP
}else{
std::cout << std::endl << "failed in ECDSAVerifysignature 02";
signatureVerifyStatus = ECDSAVerifysignature("03" + public_key_string,signature_hex);
if (signatureVerifyStatus)
{
public_key_string = "03" + public_key_string;
}else{
//CLog::log("Even failed in ECDSAVerifysignature 03","app","fatal");
std::cout << std::endl << "Even failed in ECDSAVerifysignature 03";
return {false,""};
}
}
std::cout << std::endl << "Congratulation! you've created an ECDSA key pair";
std::cout << std::endl << "Private key: " << private_key_string;
std::cout << std::endl << "Public key: " << public_key_string;
return {true,private_key_string,public_key_string};
}
int main(int argc,char *argv[])
{
auto[status,privake_key,public_key] = ECDSAGenerateKeyPair();
if (status)
{
std::cout << std::endl << "Successful ECDSA key pair generation";
}else{
std::cout << std::endl << "Failed ECDSA key pair generation";
}
}
```
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)