Elliptic Curve Cryptography

From Crypto++ Wiki
(Redirected from ECMQV)
Jump to navigation Jump to search

Elliptic Curve Cryptography (ECC) is based on the algebraic structure of elliptic curves over finite fields. The use of elliptic curves in cryptography was independently suggested by Neal Koblitz and Victor Miller in 1985.

Crypto++ offers a numbers of schemes and algorithms which operate over elliptic curves. Fields include both Fp and F2m, and schemes include:

Crypto++ conforms to Certicom's SEC 2 for most elliptic curve implementations.

Ján Jančár showed Crypto++ 8.2 and below leaked timing information in elliptic curve gear. You should upgrade to Crypto++ 8.3 and above. Also see Issue 869, Elliptic Curve timing leaks.

Two Step Construction/Initialization of Keys

If you want to perform two-step construction and initialization of a private key, then perform the following. Note that Initialize takes a RandomNumberGenerator, which causes private key generation. An Initialize that lacks the PRNG does not generate a private key.

While the example below is written for ECIES, the technique applies to all Diffie-Hellman schemes over elliptic curves due to Crypto++'s use of interface programming. That means it works equally well for ECMQV, ECDSA, ECMQV and ECNR.

// From Wei Dai in a private email
ECIES<ECP>::Decryptor d;
d.AccessKey().GenerateRandom(GlobalRNG(), MakeParameters(Name::GroupOID(), ASN1::secp256r1()));

Alternative, but non-preferred methods include the following.

ECIES<ECP>::Decryptor decryptor;
decryptor.AccessKey().AccessGroupParameters().Initialize(prng, ASN1::secp256r1());

As yet another alternative, you can set the private exponent (multiplicand) directly:

ECIES<ECP>::Decryptor decryptor;

Integer x(prng, Integer::One(), decryptor.AccessKey().GetGroupParameters().GetSubgroupOrder()-1);

Minimizing Key Size for Persistence

Keys can be serialized in a number of different formats. Some formats are better for interoperability, while others are better for minimizing size. Keys and their formats are covered in detail at Keys and Formats.

Keys and Formats does not discuss minimizing a serialized key's size. Taking from Wei Dai on the Crypto++ mailing list:

To minimize the size of public and private keys, what you need to do is

encode only the private exponent of the private key, and the public point of

the public key.

// save private exponent

// load private exponent
Integer x;

// save public element
publicKey.GetGroupParameters().GetCurve().EncodePoint(pubFile, publicKey.GetPublicElement(), true);

// load public element
ECP::Point p;
publicKey.GetGroupParameters().GetCurve().DecodePoint(p, pubFile, publicKey.GetGroupParameters().GetCurve().EncodedPointSize(true));

Curve Operations

Sometimes you may want to perform curve operations directly, and not in the context of, say, a higher level encryptor or signer. The code below shows you how to exponentiate, multiple and add using the lower level primitives over secp256r1.

#include "integer.h"
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"

#include <iostream>
#include <iomanip>

int main(int argc, char* argv[])
    using namespace CryptoPP;
    typedef DL_GroupParameters_EC<ECP> GroupParameters;
    typedef DL_GroupParameters_EC<ECP>::Element Element;

    AutoSeededRandomPool prng;    
    GroupParameters group;

    // private key
    Integer x(prng, Integer::One(), group.GetMaxExponent());
    std::cout << "Private exponent:" << std::endl;
    std::cout << "  " << std::hex << x << std::endl;
    // public key
    Element y = group.ExponentiateBase(x);

    std::cout << "Public element:" << std::endl;
    std::cout << "  " << std::hex << y.x << std::endl;
    std::cout << "  " << std::hex << y.y << std::endl;
    // element addition
    Element u = group.GetCurve().Add(y, ECP::Point(2,3));

    std::cout << "Add:" << std::endl;
    std::cout << "  " << std::hex << u.x << std::endl;
    std::cout << "  " << std::hex << u.y << std::endl;

    // scalar multiplication
    Element v = group.GetCurve().ScalarMultiply(u, Integer::Two());

    std::cout << "Mult:" << std::endl;
    std::cout << "  " << std::hex << v.x << std::endl;
    std::cout << "  " << std::hex << v.y << std::endl;

    return 0;

The program produces output similar to the following.

$ ./test.exe
Private exponent:
Public element:

Non-standard Curves

Crypto++ supplies a set of standard curves approved by ANSI, Brainpool, and NIST. Crypto++ does not provide curve generation functionality. If you need a custom curve, see Elliptic Curve Builder.


dpval-2.zip - Elliptic Curve Domain Parameter Validation. The program dumps the public and private keys, and validates the curve per Certicom's SEC 2 Whitepaper (the curve used for demonstration purposes is NIST P-192). In addition, the program demonstrates mathematics with the point of infinity and scalar multiplications using Crypto++.

ecctest.zip - Exercises encryption and decryption using ANSI, Brainpool, and NIST curves by way of #define

ECDSA-Test.zip - Crypto++ ECDSA sample program