Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

Cryptographic Interoperability: Digital Signatures

, 20 Oct 2009
Sign and verify messages using Crypto++, Java, and C#.
cryptoppinteropkeys.zip
CryptoPPInteropKeys
CryptoPPInteropKeys
cryptoppinteropsign.zip
CryptoPPInteropSign
CryptoPPInteropSign
csinteropkeys.zip
CSInteropKeys
CSInteropKeys
Properties
csinteropsign.zip
CSInteropSign
CSInteropSign
Properties
javainteropkeys.zip
JavaInteropKeys
manifest.mf
nbproject
genfiles.properties
private
private.properties
project.properties
src
JavaInteropKeys
test
javainteropsign.zip
JavaInteropSign
build
classes
JavaInteropSign
test
classes
results
manifest.mf
nbproject
genfiles.properties
private
private.properties
project.properties
src
JavaInteropSign
test
// CryptoPP.cpp
//
#include "stdafx.h"

#include <dsa.h>
using CryptoPP::DSA;
using CryptoPP::DSA_DER;
using CryptoPP::DSA_P1363;

#include <pubkey.h>
using CryptoPP::PrivateKey;
using CryptoPP::PublicKey;

#include <osrng.h>
using CryptoPP::AutoSeededRandomPool;

#include <files.h>
using CryptoPP::FileSource;
using CryptoPP::FileSink;
using CryptoPP::StringSource;
using CryptoPP::StringSink;

bool CreateDSAKeys();
bool SignDSAMessage();
bool VerifyDSAMessage();

int main(int argc, char* argv[])
{
    CreateDSAKeys();

    SignDSAMessage();

    VerifyDSAMessage();

    return 0;
}

bool CreateDSAKeys()
{
    AutoSeededRandomPool prng;

    try
    {
        // Crypto++ Key Generation
        DSA::Signer signer;        
        PrivateKey& privateKey = signer.AccessPrivateKey();
        privateKey.GenerateRandom( prng );

        DSA::Verifier verifier( signer );
        PublicKey& publicKey = verifier.AccessPublicKey();

        // Crypto++ Save Keys
        privateKey.Save(FileSink("private.dsa.cpp.key"));
        publicKey.Save(FileSink("public.dsa.cpp.key"));
    }

    catch( CryptoPP::Exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    catch( std::exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    return true;
}


bool VerifyDSAMessage()
{
    try
    {
        //
        // Crypto++ Load the Pubic Key
        //
        DSA::Verifier verifier;
        PublicKey& publicKey = verifier.AccessPublicKey();

        // publicKey.Load(FileSource("public.dsa.cpp.key", true));
        // publicKey.Load(FileSource("public.dsa.java.key", true));
        publicKey.Load(FileSource("public.dsa.cs.key", true));

        //
        // Retrieve the Message and the Signature on Message
        //
        string message, signature;

        // C++
        FileSource( "dsa.cpp.msg", true, new StringSink( message ) );
        FileSource( "dsa.cpp.sig", true, new StringSink( signature ) );

        // Java
        // FileSource( "dsa.java.msg", true, new StringSink( message ) );
        // FileSource( "dsa.java.sig", true, new StringSink( signature ) );

        // C#
        // FileSource( "dsa.cs.msg", true, new StringSink( message ) );
        // FileSource( "dsa.cs.sig", true, new StringSink( signature ) );

        //*
        // --- Begin Java Specific Conversion ---

        //
        // Convert: DER -> P1363
        //

        // Java is DER Encoded Sequence.
        // Crypto++ is P1363 format.
        /*
        {            
            // From dsa.h: If toFormat == DSA_P1363,
            //   bufferSize must equal publicKey.SignatureLength()
            size_t length = verifier.SignatureLength();

            // A buffer for the conversion
            byte* buffer = new byte[ length ];

            // Shit or Go Blind. You make the choice.
            if( !buffer ) { return false; }

            // Reuse length
            length = CryptoPP::DSAConvertSignatureFormat( 
                buffer, length, DSA_P1363, (const byte*)signature.c_str(),
                signature.length(), DSA_DER );
            
            // Reinitialize signature so that it can be used
            //   in the verifier below with minimal effort
            signature = string( (const char*)buffer, length );
            delete[] buffer;
        }
        */
        // --- End Java Specific Conversion ---
        //*/

        //
        // Verify the Signature on the Message
        //
        bool result = verifier.VerifyMessage(
            (const byte*)message.c_str(), message.length(),
            (const byte*)signature.c_str(), signature.length() );

        if( result )
        {
            cout << "Signature on Message verified" << endl;
        }
        else
        {
            cerr << "Signature on Message not verified" << endl;
            
            return false;
        }

        //
        // Convert the Message
        //
        int nChars = MultiByteToWideChar( CP_UTF8, 0,
            message.c_str(), -1, NULL, NULL );

        wchar_t* p = new wchar_t[ nChars ];
        if( !p ) { return false; }

        MultiByteToWideChar( CP_UTF8, 0, message.c_str(), -1, p, nChars );
        wstring wide( p );

        delete[] p;

    }

    catch( CryptoPP::Exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    catch( std::exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    return true;
}

bool SignDSAMessage()
{
    try
    {
        //
        // Crypto++ Load Private Key
        //
        DSA::Signer signer;        
        PrivateKey& privateKey = signer.AccessPrivateKey();        
        privateKey.Load(FileSource("private.dsa.cpp.key", true));
        
        // Convert the Message
        wstring wide = L"Crypto Interop: \u9aa8";
        int nChars = WideCharToMultiByte( CP_UTF8, 0,
            wide.c_str(), -1, NULL, 0, NULL, FALSE );

        char* p = new char[ nChars ];
        if( !p ) { return false; }

        nChars = WideCharToMultiByte( CP_UTF8, 0,
            wide.c_str(), -1, p, nChars, NULL, FALSE );

        string narrow( p );
        delete[] p;

        //
        // Sign the Message
        //

        // Set up for SignMessage()
        byte* s = new byte[ signer.MaxSignatureLength() ];
        if( !s ) { return false; }

        // Sign...
        AutoSeededRandomPool prng;
        size_t length = signer.SignMessage( prng,
            (const byte*) narrow.c_str(), narrow.length(), s );

        // Convenience
        string signature( (const char*)s, length );

        // --- Begin Java Specific Conversion ---

        //
        // Convert: P1363 -> DER
        //

        // Crypto++ uses P1363 format.
        // Java requires a DER encoded sequence.
        /*
        {
            // Determine size of required buffer
            // We can call with a null buffer and 0 size
            // when going in this direction
            length = CryptoPP::DSAConvertSignatureFormat( 
                NULL, 0, DSA_DER, (const byte*)signature.c_str(),
                signature.length(), DSA_P1363 );

            // A buffer for the conversion
            byte* buffer = new byte[ length ];

            // Shit or Go Blind. You make the choice.
            if( !buffer ) { return false; }

            // Reuse length
            length = CryptoPP::DSAConvertSignatureFormat( 
                buffer, length, DSA_DER, (const byte*)signature.c_str(),
                signature.length(), DSA_P1363 );
            
            // Reinitialize signature so that it can be used
            //   in the verifier below with minimal effort
            signature = string( (const char*)buffer, length );
            delete[] buffer;
        }
        */
        // --- End Java Specific Conversion ---

        //
        // Save the Message and the Signature on Message
        //

        // mofs: message filestream
        // sofs: signature filestream
        ofstream mofs, sofs;
        mofs.open("dsa.cpp.msg", ios_base::binary | ios_base::trunc );
        sofs.open("dsa.cpp.sig", ios_base::binary | ios_base::trunc );

        // Save Original Message
        mofs.write( narrow.c_str(), (int)narrow.length() );

        // Save Signature on Message
        sofs.write( (const char*)signature.c_str(), (int)length );

        // Cleanup
        sofs.close();
        mofs.close();
    }

    catch( CryptoPP::Exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    catch( std::exception& ex )
    {
        cerr << "Caught Error:" << endl;
        cerr << " " << ex.what() << endl;

        return false;
    }

    return true;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jeffrey Walton
Systems / Hardware Administrator
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 20 Oct 2009
Article Copyright 2008 by Jeffrey Walton
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid