问题描述
我正在尝试使用 Crypto++ 将用于密码签名的 Python 代码转换为 C++。由于我有示例代码,我认为这是一项相当简单的任务,但我在加载使用 PBKDF2 生成的私钥作为 ECDSA 的私钥时遇到了困难。但由于我不熟悉加密算法,所以我可能会错过一些东西。
Python 示例代码(取自 ErisX-REST-API-v3.3(第 9 页),您可以在此处找到:https://www.erisx.com/api-documentation/):
import hashlib
import ecdsa
from ecdsa.util import sigencode_der_canonize
import base58
def privateKeyFromPassword (authId,password):
return hashlib.pbkdf2_hmac(
hash_name= 'sha256',password=password.encode(),salt=authId.encode(),iterations= 100000,dklen= 32 )
def signMessage (message,authId,password):
privateKey = privateKeyFromPassword(authId,password)
sk = ecdsa.SigningKey.from_string(privateKey,curve=ecdsa.secp256k1)
signature = sk.sign_deterministic(
message.encode(),sigencode=sigencode_der_canonize,hashfunc=hashlib.sha256)
return base58.b58encode(signature).decode( 'ascii' )
signature = signMessage(message,password)
生成的签名是:381yXZ1tstiJroZCoFypQ19xPFus8nHqnWbJGg7oQfEA2VzocCG9ZP5erdXxM4YAkV4vcuyZBTH4g8NfYxiSHWvufPi7RGGX
这是我的 C++ 实现:
#include <iostream>
#include <cryptlib.h>
#include <pwdbased.h>
#include <sha.h>
#include <hex.h>
#include <eccrypto.h>
#include <osrng.h>
#include <asn.h>
#include <oids.h>
#include <sstream>
#include <base64.h>
int main(int n,char **args){
std::string message = "test message";
std::string authId = "12345";
int iterations= 100000;
// https://cryptopp.com/wiki/PKCS5_PBKDF2_HMAC
CryptoPP::byte password[] ="abcde";
size_t plen = strlen((const char*)password);
CryptoPP::byte salt[] = "12345"; // authID from Python code is the salt;
size_t slen = strlen((const char*)salt);
CryptoPP::byte key[32]; // dklen from the Python example
PKCS5_PBKDF2_HMAC<SHA256> pbkdf;
byte purpose = 0; // purpose is unused in PKCS5_PBKDF2_HMAC => 0.
pbkdf.DeriveKey(key,sizeof(key),purpose,password,plen,salt,slen,iterations,0.0f);
std::string result;
std::stringstream ss_result;
ss_result << "" << key;
std::cout << "(Derived) key with stringstream: " << key << std::endl;
/// Define a custom encoder for base58
// Encoder
CryptoPP::Base64Encoder encoder(new StringSink(result));
const CryptoPP::byte ALPHABET[] = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
AlgorithmParameters params = MakeParameters(Name::EncodingLookupArray(),(const byte *)ALPHABET);
encoder.IsolatedInitialize(params);
// Decoder
//int lookup[256];
//const CryptoPP::byte ALPHABET[] = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
//Base64Decoder::InitializeDecodingLookupArray(lookup,ALPHABET,58,false);
//Base64Decoder decoder;
//AlgorithmParameters params_dec = MakeParameters(Name::DecodingLookupArray(),(const int *)lookup);
//decoder.IsolatedInitialize(params_dec);
encoder.Put(key,sizeof(key));
encoder.MessageEnd();
std::cout << "(Derived) key with base58-Encoding: " << result << std::endl;
CryptoPP::AutoSeededRandomPool prng; //Create a random number
CryptoPP::ECDSA<ECP,CryptoPP::SHA256>::PrivateKey privateKey;
ECDSA<ECP,CryptoPP::SHA256>::Signer signer ( privateKey );
signer.AccessKey().Initialize(prng,CryptoPP::ASN1::secp256k1());
CryptoPP::StringSource ss2(result,true);
signer.AccessKey().Load(ss2);
std::string signature;
StringSource ss1( message,true /*pump all*/,new SignerFilter( prng,signer,new HexEncoder(new StringSink(signature))
) // SignerFilter
);
std::cout << "Signature: " << (signature) << std::endl;
}
有问题的行是 signer.AccessKey().Load(ss2);因为它在我运行编译程序时抛出以下异常:“在抛出一个 'CryptoPP::BERDecodeErr' what() 实例后调用终止:BER 解码错误”。所以我的问题是:是什么导致了这个问题?来自 PBKDF2 的私钥是否与 ECDSA 的使用不兼容? 此外,ECDSA 的 Python 实现不使用 RNG 来生成密钥。我试过 CryptoPP::NullRNG() 作为参数,但这没有用。有没有办法做到这一点,还是我必须从 Crypto++-lib 自定义函数? 代码的最后一部分使用 StringSource 创建签名。我知道它仍然使用 HexEncoder 而不是 base58Encoder。尝试将其作为参数传递的不同版本。我也很感激这里的帮助。
非常感谢您的帮助!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)