ECP::ValidateParameters() checks that !m_b.IsNegative() && m_b<p. So you
need to do b %= p at least.
But you need to figure out why VC++ is not letting your debug Crypto++. Is
it missing symbols for the DLL?
----- Original Message -----
From: "Jeffrey Walton" <[EMAIL PROTECTED]>
To: "Crypto" <[email protected]>
Sent: Friday, November 10, 2006 7:26 AM
Subject: Using Crypto++ with ECIES and User Defined Domain Parameters
// Runtime Includes
#include <iostream>
#include <string>
// Crypto++ Library
#ifdef _DEBUG
# pragma comment ( lib, "cryptlibd" )
#else
# pragma comment ( lib, "cryptlib" )
#endif
// Crypto++ Includes
#include "cryptlib.h"
#include "osrng.h" // Random Number Generator
#include "eccrypto.h" // Elliptic Curve
#include "ecp.h" // F(p) EC
#include "integer.h" // Integer Operations
#include "nbtheory.h" // ModularSquareRoot(...)
//
// Fuction Prototype
// Solves y^2 === x^3 + a*x + b (mod p)
//
CryptoPP::Integer Y(CryptoPP::Integer x, CryptoPP::Integer a,
CryptoPP::Integer b, CryptoPP::Integer p);
//
// The following parameters were generated using Elliptic Curve Builder
// ECB can be downloaded at http://www.ellipsa.net/
//
// P = 54972968989
// R = 27486254087
// S = 2
// A = 41049296989
// B = -7218879543
// P = 10067747603
// R = 10067650487
// S = 1
// A = 9184076370
// B = -320466536
// P = 62348328737
// R = 62348265779
// S = 1
// A = 29283225645
// B = -14090433241
int main(int argc, char* argv[]) {
try {
CryptoPP::AutoSeededRandomPool rng;
// User Defined Domain Parameters
CryptoPP::Integer p("62348328737");
CryptoPP::Integer n("62348265779"); // R from ECB
CryptoPP::Integer h("1"); // S from ECB, must be
<= 4
CryptoPP::Integer a("29283225645");
CryptoPP::Integer b("-14090433241");
CryptoPP::Integer x = n;
CryptoPP::Integer y = Y( x, a, b, p );
CryptoPP::ECP ec( p, a, b );
CryptoPP::ECP::Point G( x, y );
CryptoPP::ECIES< CryptoPP::ECP >::PrivateKey PrivateKey;
CryptoPP::ECIES< CryptoPP::ECP >::PublicKey PublicKey;
//
// Curve Initialization and Key Generation
//
PrivateKey.Initialize( ec, G, n, h );
PrivateKey.MakePublicKey( PublicKey );
//
// Key Validation
//
// User Defined Domain Parameters always fail, even at level 0???
//
// From cryptlib.h, Validate(...):
//
// 0 - using this object won't cause a crash or exception
(rng is ignored)
// 1 - this object will probably function (encrypt, sign,
etc.) correctly
// (but may not check for weak keys and such)
// 2 - make sure this object will function correctly, and do
reasonable
// security checks
// 3 - do checks that may take a long time
//
// if( false == PrivateKey.Validate( rng, 0 ) ) { throw
std::string( "Private Key Validation" ); }
// if( false == PublicKey.Validate( rng, 0 ) ) { throw
std::string( "Public Key Validation" ); }
// Encryptor and Decryptor
CryptoPP::ECIES< CryptoPP::ECP >::Encryptor Encryptor( PublicKey );
CryptoPP::ECIES< CryptoPP::ECP >::Decryptor Decryptor(
PrivateKey );
// Message
std::string PlainText = " ECC ";
// std::string PlainText = "ECC Test";
// std::string PlainText = "Yoda said, Do or do not. There is no
try.";
// std::string PlainText = "Winnie the Pooh said, I am a bear
of very little brain, and long words bother me.";
// Runtime Sizes...
unsigned int PlainTextLength = PlainText.length() + 1;
unsigned int CipherTextLength = Encryptor.CiphertextLength(
PlainTextLength );
if( 0 == CipherTextLength ) { throw
std::string("plaintextLength is not valid (too long)"); }
// Diagnostics
std::cout << "Plain text (" << PlainTextLength << " bytes
including the trailing '\\0'):";
std::cout << std::endl << "'" << PlainText << "'" << std::endl
<< std::endl;
// Scratch for Encryption
byte* CipherText = new byte[ CipherTextLength ];
if( NULL == CipherText ) { throw std::string( "CipherText
Allocation Failure" ); }
::memset( CipherText, 0xFB, Encryptor.CiphertextLength(
PlainTextLength ) );
// Encryption
Encryptor.Encrypt( rng, reinterpret_cast<const byte*>(
PlainText.c_str() ), PlainTextLength, CipherText );
// Scratch for Decryption
unsigned int RecoveredTextLength =
Decryptor.MaxPlaintextLength( CipherTextLength );
if( 0 == RecoveredTextLength ) { throw
std::string("ciphertextLength is not valid (too long or too short)");
}
// Decryption Buffer
char* RecoveredText = new char[ RecoveredTextLength ];
if( NULL == RecoveredText ) { throw std::string(
"RecoveredText CipherText Allocation Failure" ); }
::memset( RecoveredText, 0xFB, RecoveredTextLength );
// Decryption
Decryptor.Decrypt( rng, CipherText, CipherTextLength,
reinterpret_cast<byte*>( RecoveredText ) );
// Diagnostics
std::cout << "Recovered text (" << RecoveredTextLength << "
bytes):" << std::endl;
std::cout << "'" << RecoveredText << "'" << std::endl;
// Cleanup
if( NULL != CipherText ) { delete[] CipherText; }
if( NULL != RecoveredText ) { delete[] RecoveredText; }
}
catch( CryptoPP::Exception& e ) {
std::cerr << "Crypto++ Error: " << e.what() << std::endl;
}
catch( std::string& s ) {
std::cerr << "Error: " << s << std::endl;
}
catch (...) {
std::cerr << "Unknown Error" << std::endl;
}
return 0;
}
CryptoPP::Integer Y(CryptoPP::Integer x, CryptoPP::Integer a,
CryptoPP::Integer b, CryptoPP::Integer p)
{
// if( b < 0 ) { b += p; }
CryptoPP::Integer y = CryptoPP::a_exp_b_mod_c( x, 3, p );
y += a * x + b;
y %= p;
y = CryptoPP::ModularSquareRoot( y, p );
#ifdef _DEBUG
std::cout << std::endl;
std::cout << "Point G: " << std::endl;
std::cout << " X: " << x << std::endl;
std::cout << " Y: " << y << std::endl;
std::cout << std::endl;
#endif
//
// If y = 0, the cipher text will not decrypt properly
// In this case, generate different Domain Parameters
//
return y;
}