// 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;
}