生成压缩的 ECDSA 密钥对

问题描述

我不是密码学家,但我需要在项目中实施 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 (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...