3

私は cryptopp を初めて使用し、ECDSA 署名用の秘密鍵の作成にしばらく苦労しています。

16 進数でエンコードされたプライベート指数がありE4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFBます。これは文字列として格納されます。

これを使用して、ECDSA を使用してテキスト ブロックに署名したいと考えています。私のコードはこのように見えます

string Sig::genSignature(const string& privKeyIn, const string& messageIn)
{
   AutoSeededRandomPool prng;
   ECDSA<ECP, SHA256>::PrivateKey privateKey;
   privateKey.AccessGroupParameters().Initialize(ASN1::secp256r1());
   privateKey.Load(StringSource(privKeyIn, true, NULL).Ref());
   ECDSA<ECP, SHA256>::Signer signer(privateKey);

   // Determine maximum size, allocate a string with that size
   size_t siglen = signer.MaxSignatureLength();
   string signature(siglen, 0x00);

   // Sign, and trim signature to actual size
   siglen = signer.SignMessage(prng, (const byte *) messageIn.data(), (size_t) messageIn.length(),       (byte*)signature.data());
   signature.resize(siglen);
   cout << signature.data() << endl;
   return signature;
}

このコードは、privateKey.load(...) を実行しようとすると、Visual Studio で次のエラーを生成します。

First-chance exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.
Unhandled exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.

私は少しばかげたことをしていると思います...どんな助けでも素晴らしいでしょうか???

PSGMAC生成にECDHを使用して同様の問題がありましたが、キーをSECByteBlockとして保存することでこれを回避しましたが、この「トリック」はこの場合は機能しないようです。

4

2 に答える 2

2

DLLTest.exe: Microsoft C++ 例外: CryptoPP::BERDecodeErr ...

秘密鍵ではなく、秘密指数があります。したがって、それを呼び出すべきではありませんLoad。それが Crypto++BERDecodeErr例外の原因です。

答えはECDSA wiki ページで詳しく説明されていますが、すぐにはわかりません。privateKey指定された曲線と指数を初期化するには、次の手順を実行する必要があります::

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
exp.insert(0, "0x");

Integer x(exp.c_str());
privateKey.Initialize(ASN1::secp256r1(), x);

を先頭に追加すると"0x"Integerクラスが ASCII 文字列を正しく解析できるようになります。文字列に文字を追加することもでき"h"ます。関数の 2960 行付近のInteger.cppIntegerでクラスの解析コードを確認できます。StringToInteger


同じことを行う別の方法を次に示します。

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";

HexDecoder decoder;
decoder.Put((byte*)exp.data(), exp.size());
decoder.MessageEnd();

Integer x;
x.Decode(decoder, decoder.MaxRetrievable());

privateKey.Initialize(ASN1::secp256r1(), x);

は、ASCII からバイナリへのHexDecoder変換を実行します。が保持するバッファは、そのメソッドを使用してHexDecoder消費されます。IntegerDecode (BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED)


そして、これを使用する別の方法がありますHexDecoder(Crypto ++は、スクリプト言語と同じくらい悪い場合があります:)...

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
StringSource ss(exp, true /*punpAll*/, new HexDecoder);

Integer x;
x.Decode(ss, ss.MaxRetrievable());

privateKey.Initialize(ASN1::secp256r1(), x);

キーを初期化したら、それを検証する必要があります。

bool result = privateKey.Validate( prng, 3 );
if( !result ) { /* Handle error */ }

これにより、バイナリデータが出力されます。

cout << signature.data() << endl;

印刷可能/読み取り可能なものが必要な場合は、 Crypto++ HexEncoderを介して実行します。

于 2014-12-01T16:04:06.830 に答える