与 XTR-DH Crypto++ 的密钥协议

Key agreement with XTR-DH Crypto++

我尝试将 XTR-DH 用于此示例的密钥协议:

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

这是我的代码:

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

我遇到了这个错误

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  

我的问题是:

  1. 发电机编号为c1和c2。 make xtrB 需要两者还是只需要一个?
  2. 我已经尝试从 xtrA 中获取 p、q 和 g 的数量并将其输入以用于 xtrB 的启动,但它对于整数来说太长了。什么解决方案?

先致谢

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

您应该使用 XTR-DH | Constructors 中的以下构造函数:

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

有两种设置方法xtrB。一、构造器的使用方式(以及人为的小参数):

$ 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;
}

然后:

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

其次,在ASN.1对象中存储域参数的方式(以及人为的小参数):

$ 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;
}

然后:

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

最后:

$ 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
       :   }

在实践中你可能想使用这样的东西,它在加载参数后验证它们。您应该始终验证您的安全参数。

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

您可能会使用上面显示的第二种方法。也就是说,您将一次性生成您的域参数,然后双方都将使用它们。下面双方 xtrAxtrB 使用 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");

    ...
}