Hi All,

I've generated Domain Parameters T as shown below. They pass the Certicom
Validation Primitive (Section 3.1.1.2.1), but Crypto++ Validate fails even
at level 1 ('weaks keys and such' are not tested). Any ideas? The curve does
Validate at Level 3.

What I see:
Generated Cofactor f = 2. When passed into Crypto++ (through parameter k):
 Sub Group Order n: 5186044226273133563273371929482314
        Cofactor k: 1
    Max Exponent m: 5186044226273133563273371929482313
     Private Exp e: 2

I _ASSUMED_ k is the cofactor because m_k is returned through GetCofactor().

  CryptoPP::ECP ec( p, a, b );

  CryptoPP::ECIES< CryptoPP::ECP >::PrivateKey    PrivateKey;
  CryptoPP::ECIES< CryptoPP::ECP >::PublicKey     PublicKey;

  // Curve Initialization and Key Generation
  PrivateKey.Initialize( ec, CryptoPP::ECP::Point( x, y ), n, f );
  PrivateKey.MakePublicKey( PublicKey );
Jeff

 p appears to be prime... OK
 a is in the interval [0, p-1]... OK
 b is in the interval [0, p-1]... OK
 x is in the interval [0, p-1]... OK
 y is in the interval [0, p-1]... OK
 Discriminant != 0 (mod p)... OK
 Base Point G(x,y) is on E(GF(p))... OK
 n appears to be prime... OK
 h <= 4... OK
 h = FLOOR((SQRT(p)+1)^2 / n)... OK
 nG = O... OK
 p^B != 1 (mod n) for any 1 <= B < 20... OK
 n*h != p... OK

Public Key:
 EC Parameter p: 5186044226273133699992338255370617
                 112 bits
 EC Parameter a: 2757214153910325245522685003043920
 EC Parameter b: 1175514487796170316401010612487484
   Base Point x: 4052281606118159132919127812645338
   Base Point y: 1465818003156267745766136355594228

Private Key:
      Base Point x: 4052281606118159132919127812645338
      Base Point y: 1465818003156267745766136355594228
     Group Order r: 5186044226273133563273371929482314
 Sub Group Order n: 5186044226273133563273371929482314
        Cofactor k: 1
    Max Exponent m: 5186044226273133563273371929482313
     Private Exp e: 2

Error: Private Key Validation Failure

===================================

Source File

===================================

// Runtime Includes
#include <iostream>

// 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"   // VerifyPrime and ModularRoot

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

// Returns 4*a^3 + 27*b^2 (mod p) (Discriminant)
CryptoPP::Integer D( CryptoPP::Integer a, CryptoPP::Integer b,
CryptoPP::Integer p );

void Validate( CryptoPP::Integer p, CryptoPP::Integer a, CryptoPP::Integer
b,
              CryptoPP::Integer x, CryptoPP::Integer y,
              CryptoPP::Integer n, CryptoPP::Integer k );
// Debug
void DumpPublicKey( const CryptoPP::ECIES< CryptoPP::ECP >::PublicKey&
PublicKey );
void DumpPrivateKey( const CryptoPP::ECIES< CryptoPP::ECP >::PrivateKey&
PrivateKey );

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

   CryptoPP::AutoSeededRandomPool rng;

   try {

       // User Defined Domain Parameters
       CryptoPP::Integer p("5186044226273133699992338255370617");

       // a
       CryptoPP::Integer a("2757214153910325245522685003043920");
       // b
       CryptoPP::Integer b("1175514487796170316401010612487484");

       // Cofactor (f) and Order (r)
       CryptoPP::Integer f = 2;
       CryptoPP::Integer r("2593022113136566781636685964741157");

       // n: n = f * r
       CryptoPP::Integer n = f * r;

       // x, y: Base Point G
       CryptoPP::Integer x("-1133762620154974567073210442725279");
       CryptoPP::Integer y("1465818003156267745766136355594228");

       // bring back to the interval [0, p-1]
       a %= p; b %= p; x %= p; y %= p;

       CryptoPP::ECP ec( p, a, b );

       CryptoPP::ECIES< CryptoPP::ECP >::PrivateKey    PrivateKey;
       CryptoPP::ECIES< CryptoPP::ECP >::PublicKey     PublicKey;

       // Curve Initialization and Key Generation
       PrivateKey.Initialize( ec, CryptoPP::ECP::Point( x, y ), n, f );
       PrivateKey.MakePublicKey( PublicKey );

       Validate( p, a, b, x, y, r, f );    std::cout << std::endl;

       DumpPublicKey( PublicKey );         std::cout << std::endl;

       DumpPrivateKey( PrivateKey );       std::cout << std::endl;

       if( false == ec.ValidateParameters( rng, 3 ) )
           { throw std::string("EC Parameter Validation Failure"); }

       if( false == PrivateKey.Validate( rng, 1 ) )
           { throw std::string("Private Key Validation Failure"); }

       if( false == PublicKey.Validate( rng, 1 ) )
           { throw std::string("Public Key Validation Failure"); }
   }

   catch( CryptoPP::Exception& e )
       { std::cerr << "Error: " << e.what() << std::endl; }

   catch( std::string& s )
       { std::cerr << "Error: " << s << std::endl; }

   catch (...)
       { std::cerr << "Unknown Error" << std::endl; }

return 0;
}

void DumpPublicKey( const CryptoPP::ECIES< CryptoPP::ECP >::PublicKey&
PublicKey )
{
   std::cout << "Public Key:" << std::endl;

   CryptoPP::Integer p = PublicKey.GetGroupParameters
().GetCurve().FieldSize();
   std::cout << "  EC Parameter p: " << p << std::endl;
   std::cout << "                  " << p.BitCount() << " bits" <<
std::endl;

   CryptoPP::Integer a = PublicKey.GetGroupParameters().GetCurve().GetA();
   std::cout << "  EC Parameter a: " << a << std::endl;

   CryptoPP::Integer b = PublicKey.GetGroupParameters().GetCurve().GetB();
   std::cout << "  EC Parameter b: " << b << std::endl;

   CryptoPP::Integer x = PublicKey.GetGroupParameters
().GetSubgroupGenerator().x;
   std::cout << "    Base Point x: " << x << std::endl;

   CryptoPP::Integer y = PublicKey.GetGroupParameters
().GetSubgroupGenerator().y;
   std::cout << "    Base Point y: " << y << std::endl;

   // CryptoPP::Integer e = PublicKey.GetGroupParameters
().GetPublicExponent();
   // std::cout << "    Public Exp e: " << e << std::endl;
}

void DumpPrivateKey( const CryptoPP::ECIES< CryptoPP::ECP >::PrivateKey&
PrivateKey )
{
   std::cout << "Private Key:" << std::endl;

   CryptoPP::Integer x = PrivateKey.GetGroupParameters
().GetSubgroupGenerator().x;
   std::cout << "       Base Point x: " << x << std::endl;

   CryptoPP::Integer y = PrivateKey.GetGroupParameters
().GetSubgroupGenerator().y;
   std::cout << "       Base Point y: " << y << std::endl;

   CryptoPP::Integer r = PrivateKey.GetGroupParameters().GetGroupOrder();
   std::cout << "      Group Order r: " << r << std::endl;

   CryptoPP::Integer n = PrivateKey.GetGroupParameters
().GetSubgroupOrder();
   std::cout << "  Sub Group Order n: " << n << std::endl;

   CryptoPP::Integer k = PrivateKey.GetGroupParameters().GetCofactor();
   std::cout << "         Cofactor k: " << k << std::endl;

   CryptoPP::Integer m = PrivateKey.GetAbstractGroupParameters
().GetMaxExponent();
   std::cout << "     Max Exponent m: " << m << std::endl;

   CryptoPP::Integer e = PrivateKey.GetPrivateExponent();
   std::cout << "      Private Exp e: " << e << std::endl;
}

// Standards for Efficient Cryptography
// SEC 1: Elliptic Curve Cryptography
//   Elliptic Curve Domain Parameters over GF(p) Validation, pp 17-18
void Validate( CryptoPP::Integer p, CryptoPP::Integer a, CryptoPP::Integer
b,
              CryptoPP::Integer x, CryptoPP::Integer y,
              CryptoPP::Integer n, CryptoPP::Integer h )
{

   CryptoPP::Integer t;
   CryptoPP::AutoSeededRandomPool rng;

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 1: p is an odd prime...
   if( true == CryptoPP::VerifyPrime( rng, p, 6 ) )
   {
       std::cout << "  p appears to be prime... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** p is composite **" << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 1: [p] ... such that t = { 56, 64, ..., 192, 256 }
   // This needs to be tightened...
   if( p.BitCount() / 2 >= 56 )
   {
       // { std::cout << "  t = { 56, 64, 80, 96, 112, 128, 192, 256}...
OK" << std::endl; }
   }
   else
   {
       { std::cout << "  ** Security Level t may be too small **" <<
std::endl; }
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 2: a, b, g_x, g_y = [0, p-1]
   t = p - 1;
   if( a >= 0 && a <= t )
       { std::cout << "  a is in the interval [0, p-1]... OK" << std::endl;
}
   else
   {
       std::cout << "  ** a is not in the interval [0, p-1] **" <<
std::endl;
       std::cout << "    a: " << a << std::endl;
   }

   if( b >= 0 && b <= t )
       { std::cout << "  b is in the interval [0, p-1]... OK" << std::endl;
}
   else
   {
       std::cout << "  ** b is not in the interval [0, p-1] **" <<
std::endl;
       std::cout << "    b: " << b << std::endl;
   }

   if( x >= 0 && x <= t )
       { std::cout << "  x is in the interval [0, p-1]... OK" << std::endl;
}
   else
   {
       std::cout << "  ** x is not in the interval [0, p-1] **" <<
std::endl;
       std::cout << "    x: " << x << std::endl;
   }

   if( y >= 0 && y <= t )
       { std::cout << "  y is in the interval [0, p-1]... OK" << std::endl;
}
   else
   {
       std::cout << "  ** y is not in the interval [0, p-1] **" <<
std::endl;
       std::cout << "    y: " << y << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 3: 4*a^3 + 27*b^2 != 0 (mod p)
   t = D( a, b, p );
   if( 0 != t )
   {
       std::cout << "  Discriminant != 0 (mod p)... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** Discriminant == 0 (mod p) **" << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 4: y^2 == x^3 + a*x + b (mod p)
   t = Y( x, a, b, p );
   if( t % p != y % p )
   {
       std::cout << "  Base Point G(x,y) is on E(GF(p))... OK" <<
std::endl;
   }
   else
   {
       std::cout << "  ** Base Point G(x,y) is not on E(GF(p)) **" <<
std::endl;
       std::cout << "     y^2: " << y.Squared() % p << std::endl;
       std::cout << "  f(y^2): " << (x*(x.Squared()+1)+b)%p << std::endl;

   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 5: n is an odd prime...
   if( true == CryptoPP::VerifyPrime( rng, n, 6 ) )
   {
       std::cout << "  n appears to be prime... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** n is composite **" << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 6: h <= 4 ...
   if( h <= 4  )
   {
       std::cout << "  h <= 4... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** h is too large **" << std::endl;
       std::cout << "  h: " << h << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 6: ... h = FLOOR( (SQRT(P)+1)^2 / n )
   t = p.SquareRoot() + 1;
   t = t.Squared() / n;
   if( h == t )
   {
       std::cout << "  h = FLOOR((SQRT(p)+1)^2 / n)... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** h != FLOOR( (SQRT(p)+1)^2 / n ) **" << std::endl;
       std::cout << "  f(h): " << t << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 7: n*G = O (O is Point of Infinity)
   CryptoPP::ECP ec( p, a, b );
   if( ec.Identity() == ec.ScalarMultiply( CryptoPP::ECPPoint(x, y), n ) )
   {
       std::cout << "  nG = O... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** nG != O **" << std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 8: q^B != 1 (mod n) for any 1 <= B < 20 ...
   bool bResult = true;
   for( unsigned int B = 1; B < 20 && true == bResult; B++ )
   {
       bResult |= ( 1 != CryptoPP::a_exp_b_mod_c( p, B, p ) );
   }
   if( true == bResult )
   {
       std::cout << "  p^B != 1 (mod n) for any 1 <= B < 20... OK" <<
std::endl;
   }
   else
   {
       std::cout << "  ** p^B = 1 (mod n) for B = " << B << " **" <<
std::endl;
   }

   // SEC1, Section 3.1.1.2.1, page 18
   //   Check 8: ... n*h != p
   if( p != n * h )
   {
       std::cout << "  n*h != p... OK" << std::endl;
   }
   else
   {
       std::cout << "  ** n*h = p **" << std::endl;
   }
}

CryptoPP::Integer Y( CryptoPP::Integer x, CryptoPP::Integer a,
                    CryptoPP::Integer b, CryptoPP::Integer p )
{
   x %= p; a %= p; b %= p;

   CryptoPP::Integer y = CryptoPP::a_exp_b_mod_c( x, 3, p );
   y += a * x + b;
   return CryptoPP::ModularSquareRoot( y % p, p );
}

CryptoPP::Integer D( CryptoPP::Integer a, CryptoPP::Integer b,
CryptoPP::Integer p )
{
   CryptoPP::Integer d = 4 * CryptoPP::a_exp_b_mod_c( a, 3, p );
   d += 27 * b.Squared();

   return d % p;
}

Reply via email to