4
votes

I am currently having trouble signing/verifying a string with Crypto++. I have tried methods listed on this website among others, for months, with no success. I have previously tried the C style solution posted here: http://www.cryptopp.com/wiki/Elliptic_Curve_Digital_Signature_Algorithm, but am currently working on the implementation using filters.

My attempt below is a modification of the solution posted here: Get ECDSA signature with Crypto++.

The following code outputs the error: ERROR: VerifierFilter: digital signature not valid

ECDSA<ECP, SHA256>::PrivateKey privateKey;
ECDSA<ECP, SHA256>::PublicKey publicKey;

AutoSeededRandomPool prng, rrng;

privateKey.Initialize(prng, CryptoPP::ASN1::secp256k1());

privateKey.MakePublicKey(publicKey);

string signature;

signature.erase();

string message = "Do or do not. There is no try.";

StringSource(message, true,
     new SignerFilter(rrng,
     ECDSA<ECP, SHA256>::Signer(privateKey),
     new StringSink(signature)));

 try
 {
     StringSource(signature + message, true,
         new SignatureVerificationFilter(
         ECDSA<ECP, SHA256>::Verifier(publicKey), NULL,
         SignatureVerificationFilter::THROW_EXCEPTION
         ) // SignatureVerificationFilter   
         ); // StringSource 
 }
 catch (CryptoPP::Exception& e)
 {
     std::cerr << "\n\nERROR: " << e.what() << std::endl;
 }

Any help is appreciated, thanks.

2

2 Answers

3
votes

After browsing the Wiki longer, I think I may have stumbled on the solution.

http://www.cryptopp.com/wiki/SignatureVerificationFilter#Signature_Generation_and_Verification

In the example above, the filter receives a concatenation of message+signature. When SIGNATURE_AT_BEGIN is not specified in the constructor, SIGNATURE_AT_END is implied and the signature to be verified must be presented after the message. If the signature is inserted first, SIGNATURE_AT_BEGIN must be be specified as an additional flags value as shown below.

Because THROW_EXCEPTION is used, signature and message must be swapped, or SIGNATURE_AT_BEGIN must be added. In this case, the following code does not throw an exception.

StringSource ss(signature + message, true,
    new SignatureVerificationFilter(
    verifier, NULL,
    THROW_EXCEPTION | SIGNATURE_AT_BEGIN
        ) // SignatureVerificationFilter   
        ); // StringSource  
0
votes
StringSource(signature + message, true,
    new SignatureVerificationFilter(
        ECDSA<ECP, SHA256>::Verifier(publicKey), NULL,
        SignatureVerificationFilter::THROW_EXCEPTION
    ) // SignatureVerificationFilter   
); //

The above looks fishy. It looks fishy for two reasons. First, it uses anonymous declarations, and I know some versions of GCC gives bad results with them. GCC generates code such that the destructors run too soon. So name your declaration.

Second, the SignatureVerificationFilter takes a reference, and not a temporary. So you should provide a reference to the verifier, or use the Ref() member function if its available.

First, try with just:

ECDSA<ECP, SHA256>::Verifier verifier(publicKey);

StringSource ss(signature + message, true,
    new SignatureVerificationFilter(
        verifier, NULL,
        SignatureVerificationFilter::THROW_EXCEPTION
    ) // SignatureVerificationFilter   
); // StringSource 

Second, try with:

StringSource ss(signature + message, true,
    new SignatureVerificationFilter(
        ECDSA<ECP, SHA256>::Verifier(publicKey).Ref(), NULL,
        SignatureVerificationFilter::THROW_EXCEPTION
    ) // SignatureVerificationFilter   
); // StringSource

But I'm not sure if ECDSA<ECP, SHA256>::Verifier(publicKey).Ref() is going to work.