Search code examples
c++cryptographycrypto++

Key agreement with XTR-DH Crypto++


I try applied XTR-DH for Key Agreement with this example:

//////////////////////////////////////////////////////////////////////////
// Alice

// Initialize the Diffie-Hellman class with a random prime and base
AutoSeededRandomPool rngA;
DH dhA;
dh.Initialize(rngA, 128);

// Extract the prime and base. These values could also have been hard coded 
// in the application
Integer iPrime = dhA.GetGroupParameters().GetModulus();
Integer iGenerator = dhA.GetGroupParameters().GetSubgroupGenerator();

SecByteBlock privA(dhA.PrivateKeyLength());
SecByteBlock pubA(dhA.PublicKeyLength());
SecByteBlock secretKeyA(dhA.AgreedValueLength());

// Generate a pair of integers for Alice. The public integer is forwarded to Bob.
dhA.GenerateKeyPair(rngA, privA, pubA);

//////////////////////////////////////////////////////////////////////////
// Bob

AutoSeededRandomPool rngB;
// Initialize the Diffie-Hellman class with the prime and base that Alice generated.
DH dhB(iPrime, iGenerator);

SecByteBlock privB(dhB.PrivateKeyLength());
SecByteBlock pubB(dhB.PublicKeyLength());
SecByteBlock secretKeyB(dhB.AgreedValueLength());

// Generate a pair of integers for Bob. The public integer is forwarded to Alice.
dhB.GenerateKeyPair(rngB, privB, pubB);

//////////////////////////////////////////////////////////////////////////
// Agreement

// Alice calculates the secret key based on her private integer as well as the
// public integer she received from Bob.
if (!dhA.Agree(secretKeyA, privA, pubB))
    return false;

// Bob calculates the secret key based on his private integer as well as the
// public integer he received from Alice.
if (!dhB.Agree(secretKeyB, privB, pubA))
    return false;

// Just a validation check. Did Alice and Bob agree on the same secret key?
if (VerifyBufsEqualp(secretKeyA.begin(), secretKeyB.begin(), dhA.AgreedValueLength()))
    return false;

return true;

And here my code :

//Alice

AutoSeededRandomPool aSRPA;
XTR_DH xtrA(aSRPA, 512, 256);
Integer iPrime = xtrA.GetModulus();
Integer i_qnumber = xtrA.GetSubgroupOrder();
Integer iGeneratorc1 = xtrA.GetSubgroupGenerator().c1;
Integer iGeneratorc2 = xtrA.GetSubgroupGenerator().c2;

SecByteBlock privateA(xtrA.PrivateKeyLength());
SecByteBlock publicA(xtrA.PublicKeyLength());
SecByteBlock secretKeyA(xtrA.AgreedValueLength());
xtrA.GenerateKeyPair(aSRPA, privateA, publicA);

//Bob

AutoSeededRandomPool aSRPB;

XTR_DH xtrB(iPrime, i_qnumber, iGeneratorc1); // Use c1 or c2 or both ???

SecByteBlock privB(xtrB.PrivateKeyLength());
SecByteBlock publB(xtrB.PublicKeyLength());
SecByteBlock secretKeyB(xtrB.AgreedValueLength());

xtrB.GenerateKeyPair(aSRPB, privateB, publicB);

// Agreement

// Alice calculates the secret key based on her private integer as well as the
// public integer she received from Bob.
if (!xtrA.Agree(secretKeyA, privateA, publicB))
    return false;

// Bob calculates the secret key based on his private integer as well as the
// public integer he received from Alice.
if (!xtrB.Agree(secretKeyB, privateB, publicA))
        return false;

// Just a validation check. Did Alice and Bob agree on the same secret key?
if (VerifyBufsEqualp(secretKeyA.begin(), secretKeyB.begin(), xtrA.AgreedValueLength()))
    return false;

return true;

I got this error

Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'CryptoPP::XTR_DH::XTR_DH(CryptoPP::XTR_DH &&)': cannot convert argument 3 from 'CryptoPP::Integer' to 'const CryptoPP::GFP2Element &'  ConsoleApplication1 d:\tugas akhir\code\consoleapplication1\consoleapplication1\consoleapplication1.cpp 91  

My question is :

  1. Number of generator is c1 and c2. Is it need both for make xtrB or just one ?
  2. I have tried take number of p, q and g from xtrA and input it for initiate for xtrB but its too long for integer. What the solution ?

Thanks before


Solution

  • XTR_DH xtrB(iPrime, i_qnumber, iGeneratorc1); // Use c1 or c2 or both ???
    

    You should use the the following constructor from XTR-DH | Constructors:

    XTR_DH (const Integer &p, const Integer &q, const GFP2Element &g)
    

    There are two ways to setup xtrB. First, the way that uses the constructor (and artificially small parameters):

    $ cat test.cxx
    #include "cryptlib.h"
    #include "osrng.h"
    #include "xtrcrypt.h"
    
    #include <iostream>
    
    int main()
    {
        using namespace CryptoPP;
    
        AutoSeededRandomPool aSRP;
        XTR_DH xtrA(aSRP, 170, 160);
    
        const Integer& iPrime = xtrA.GetModulus();
        const Integer& iOrder = xtrA.GetSubgroupOrder();
        const GFP2Element& iGenerator = xtrA.GetSubgroupGenerator();
    
        XTR_DH xtrB(iPrime, iOrder, iGenerator);
    
        std::cout << "Prime: " << std::hex << xtrB.GetModulus() << std::endl;
        std::cout << "Order: " << std::hex << xtrB.GetSubgroupOrder() << std::endl;
        std::cout << "Generator" << std::endl;
        std::cout << "  c1: " << std::hex << xtrB.GetSubgroupGenerator().c1 << std::endl;
        std::cout << "  c2: " << std::hex << xtrB.GetSubgroupGenerator().c2 << std::endl;
    
        return 0;
    }
    

    And then:

    $ g++ -DNDEBUG -g2 -O3 -fPIC -pthread test.cxx ./libcryptopp.a -o test.exe
    $ ./test.exe
    Prime: 2d4c4f9f4de9e32e84a7be42f019a1a4139e0fe7489h
    Order: 89ab07fa5115443f51ce9a74283affaae2d7748fh
    Generator
      c1: 684fedbae519cb297f3448d5e564838ede5ed1fb81h
      c2: 39112823212ccd7b01f10377536f51bf855752c7a3h
    

    Second, the way that stores the domain parameters in an ASN.1 object (and artificially small parameters):

    $ cat test.cxx
    #include "cryptlib.h"
    #include "osrng.h"
    #include "files.h"
    #include "xtrcrypt.h"
    
    #include <iostream>
    
    int main()
    {
        using namespace CryptoPP;
    
        AutoSeededRandomPool prng;
        XTR_DH xtrA(prng, 170, 160);
        xtrA.DEREncode(FileSink("params.der").Ref());
        XTR_DH xtrB(FileSource("params.der", true).Ref());
    
        std::cout << "Prime: " << std::hex << xtrB.GetModulus() << std::endl;
        std::cout << "Order: " << std::hex << xtrB.GetSubgroupOrder() << std::endl;
        std::cout << "Generator" << std::endl;
        std::cout << "  c1: " << std::hex << xtrB.GetSubgroupGenerator().c1 << std::endl;
        std::cout << "  c2: " << std::hex << xtrB.GetSubgroupGenerator().c2 << std::endl;
    
        return 0;
    }
    

    And then:

    $ g++ -DNDEBUG -g2 -O3 -fPIC -pthread test.cxx ./libcryptopp.a -o test.exe
    $ ./test.exe
    Prime: 2ee076b3254c1520151bbe0391a77971f92e277ba37h
    Order: f7674a8c2dd68d32c3da8e74874a48b9adf00fcbh
    Generator
      c1: 2d469e63b474ac45578a0027a38864f303fad03ba9h
      c2: 1d5e5714bc19ef25eee0535584176889df8f26c4802h
    

    And finally:

    $ dumpasn1 params.der
      0  94: SEQUENCE {
      2  22:   INTEGER 02 EE 07 6B 32 54 C1 52 01 51 BB E0 39 1A 77 97 1F 92 E2 77 BA 37
     26  21:   INTEGER 00 F7 67 4A 8C 2D D6 8D 32 C3 DA 8E 74 87 4A 48 B9 AD F0 0F CB
     49  21:   INTEGER 2D 46 9E 63 B4 74 AC 45 57 8A 00 27 A3 88 64 F3 03 FA D0 3B A9
     72  22:   INTEGER 01 D5 E5 71 4B C1 9E F2 5E EE 05 35 58 41 76 88 9D F8 F2 6C 48 02
           :   }
    

    In practice you probably want to use something like this, which validates the parameters after loading them. You should always validate your security parameters.

    // Load the domain parameters from somewhere
    const Integer& iPrime = ...;
    const Integer& iOrder = ...;
    const GFP2Element& iGenerator = ...;
    
    // Create the key agreement object using the parameters
    XTR_DH xtrB(iPrime, iOrder, iGenerator);
    
    // Verify the the parameters using the key agreement object
    if(xtrB.Validate(aSRP, 3) == false)
        throw std::runtime_error("Failed to validate parameters");
    

    You are probably going to use something like the second method shown above. That is, you are going to generate your domain parameters once, and then both parties will use them. Below both parties xtrA and xtrB use params.der:

    int main()
    {
        using namespace CryptoPP;
    
        AutoSeededRandomPool prng;
        XTR_DH xtrA(FileSource("params.der", true).Ref());
        XTR_DH xtrB(FileSource("params.der", true).Ref());
    
        if(xtrA.Validate(prng, 3) == false)
            throw std::runtime_error("Failed to validate parameters");
    
        if(xtrB.Validate(prng, 3) == false)
            throw std::runtime_error("Failed to validate parameters");
    
        ...
    }