Question

I have downloaded the CryptoPP library and I am able to run the sample codes and get results (for CCM and GCM modes).

The next step for me is to try out the test vectors for each of these modes. From my understanding im suppose to try out the different keys, IVs and plaintexts as specified in the test vectors. Then I have to verify that the expected results are also specified in each vector.

What I can seem to understand is how to input these keys and IVs for the vectors. From the code as shown below, it seems to be using a random key.

Preferably I would like to input the keys and IVs from command prompt and then run the test code. Just setting the vectors from the code in Visual Studio would do though.

Please find the sample code and one of the vectors below:

Sample Code:

AutoSeededRandomPool prng;

SecByteBlock key( AES::DEFAULT_KEYLENGTH );
prng.GenerateBlock( key, key.size() );

byte iv[ AES::BLOCKSIZE * 16 ];
prng.GenerateBlock( iv, sizeof(iv) );    

const int TAG_SIZE = 12;

// Plain text
string pdata="Authenticated Encryption";

// Encrypted, with Tag
string cipher, encoded;

// Recovered plain text
string rpdata;

/*********************************\
\*********************************/

try
{
    GCM< AES >::Encryption e;
    e.SetKeyWithIV( key, key.size(), iv, sizeof(iv) );

    StringSource( pdata, true,
        new AuthenticatedEncryptionFilter( e,
            new StringSink( cipher ), false, TAG_SIZE
        ) // AuthenticatedEncryptionFilter
    ); // StringSource
}
catch( CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

try
{
    GCM< AES >::Decryption d;
    d.SetKeyWithIV( key, key.size(), iv, sizeof(iv) );

    AuthenticatedDecryptionFilter df( d,
        new StringSink( rpdata ),
        DEFAULT_FLAGS, TAG_SIZE
    ); // AuthenticatedDecryptionFilter

    // The StringSource dtor will be called immediately
    //  after construction below. This will cause the
    //  destruction of objects it owns. To stop the
    //  behavior so we can get the decoding result from
    //  the DecryptionFilter, we must use a redirector
    //  or manually Put(...) into the filter without
    //  using a StringSource.
    StringSource( cipher, true,
        new Redirector( df /*, PASS_EVERYTHING */ )
    ); // StringSource

    // If the object does not throw, here's the only
    //  opportunity to check the data's integrity
    if( true == df.GetLastResult() ) {
        cout << "recovered text: " << rpdata << endl;
    }
}
catch( CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

One of the vectors:

GCM Test Case #14 (AES-256)
Variable          Value
-------------------------------------------------
K               : 00000000000000000000000000000000
                : 00000000000000000000000000000000
P               : 00000000000000000000000000000000
IV              : 000000000000000000000000
H               : dc95c078a2408989ad48a21492842087
Y_0             : 00000000000000000000000000000001
E(K,Y_0)        : 530f8afbc74536b9a963b4f1c4cb738b
Y_1             : 00000000000000000000000000000002
E(K,Y_1)        : cea7403d4d606b6e074ec5d3baf39d18
X_1             : fd6ab7586e556dba06d69cfe6223b262
len(A)||len(C)  : 00000000000000000000000000000080
GHASH(H,A,C)    : 83de425c5edc5d498f382c441041ca92
C               : cea7403d4d606b6e074ec5d3baf39d18

T               : d0d1c8a799996bf0265b98b5d48ab919
Was it helpful?

Solution

I have downloaded the CryptoPP library and I am able to run the sample codes and get results (for CCM and GCM modes).

Crypto++ does not use the examples from its wiki when running its self tests. The self test code is much more hairier.

What I can seem to understand is how to input these keys and IVs for the vectors. From the code as shown below, it seems to be using a random key.

The Crypto++ test vectors are located in <crypto++ dir>/TestVectors. I don't believe the vector you show in your question is from Crypto++. For example, here's from <crypto++ dir>/TestVectors/gcm.txt:

AlgorithmType: AuthenticatedSymmetricCipher
Name: AES/GCM
Source: aes-modes-src-07-10-08/Testvals/gcm.1, Basic Tests for GCM (compiled by B. R. Gladman)
Key: 00000000000000000000000000000000
IV:  000000000000000000000000
MAC: 00000000000000000000000000000000 
Test: NotVerify
Key: 00000000000000000000000000000000
IV:  000000000000000000000000
MAC: 58e2fccefa7e3061367f1d57a4e7455a 
Test: Encrypt
Key: 00000000000000000000000000000000
IV:  000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: 0388dace60b6a392f328c2b971b2fe78
MAC: ab6e47d42cec13bdf53a67b21257bddf 
Test: Encrypt
...

You can see how the Crypto++ test suite consumes it when you use the cryptest.exe v command. The source files that execute the self tests are validat1.cpp, validat2.cpp and validat3.cpp. The GCM testing starts in validat1.cpp on line 95:

pass=ValidateGCM() && pass;

Here's ValidateGCM around line 1395:

bool ValidateGCM()
{
    cout << "\nAES/GCM validation suite running...\n";
    cout << "\n2K tables:";
    bool pass = RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)2048));
    cout << "\n64K tables:";
    return RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)64*1024)) && pass;
}

Its a real pain to untangle RunTestDataFile, TestDataFile and TestAuthenticatedSymmetricCipher (and friends). They are implemented in datatest.cpp. The pain point is TestAuthenticatedSymmetricCipher around line 450 of datatest.cpp.

I usually go to the applicable standard, pull the test vectors, and then write my own self tests. In the case of deterministic encryption like AES/GCM, you can write a Known Answer Test (KAT). For non-deterministic tests, you will need to write a Pairwise Consistency Test (PCT). Essentially, you verify you can round trip data from a public/private key pair operation, like a DH or RSA key.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top