ElGamal加密示例?

时间:2013-11-14 10:02:10

标签: c++ crypto++ elgamal

我提前为这个问题提出了道歉,但是我已经被困住了很长时间,而且我正在努力弄清楚接下来要做什么。基本上,我试图对某些数据执行ElGamal加密。我已经获得了一个临时密钥对和第二个静态密钥的公共部分,以及一些数据。如果我的理解是正确的,这就是我需要执行加密,但我很难弄清楚如何使用Crypto ++。

我无休止地看了一些例子,但我可以在谷歌上找到零。 Ohloh不太有用,因为我只是回到了无数页的cryptopp ElGamal源文件,我似乎无法弄清楚(我使用Crypto ++相对较新,直到大约3天前还没有听说过ElGamal)。

我能找到的最接近的例子来自CryptoPP软件包本身,如下所示:

bool ValidateElGamal()
{
    cout << "\nElGamal validation suite running...\n\n";
    bool pass = true;
    {
        FileSource fc("TestData/elgc1024.dat", true, new HexDecoder);
        ElGamalDecryptor privC(fc);
        ElGamalEncryptor pubC(privC);
        privC.AccessKey().Precompute();
        ByteQueue queue;
        privC.AccessKey().SavePrecomputation(queue);
        privC.AccessKey().LoadPrecomputation(queue);

        pass = CryptoSystemValidate(privC, pubC) && pass;
    }
    return pass;
}

然而,这似乎并没有真正帮助我,因为我不知道如何插入我已经计算过的值。我不确定我是否正在努力理解Elgamal如何工作(完全可能),或者当我使用CryptoPP所拥有的东西时,我只是一个白痴。任何人都可以帮助我指出正确的方向吗?

1 个答案:

答案 0 :(得分:1)

  

我获得了短暂密钥对和第二个静态密钥的公共部分,以及一些数据。

我们在这里无法真正帮助你,因为我们对应该做什么一无所知。

临时密钥对可能用于模拟密钥交换,静态密钥是用于签署短暂交换的长期密钥。除此之外,任何人都猜测发生了什么。

你碰巧知道钥匙是什么吗? Diffie-Hellman密钥是短暂的关键,而ElGamal签名密钥是静态密钥吗?


  

如果我的理解是正确的,那么我只需要执行加密,但我很难弄清楚如何使用Crypto ++。

对于加密示例,我要作弊并使用RSA encryption example并将其移植到ElGamal。这与复制和粘贴一样困难,因为RSA加密和ElGamal encryption都遵循PK_EncryptorPK_Decryptor接口。有关详细信息,请参阅PK_EncryptorPK_Decryptor类。 (请记住,您可能需要一个ElGamal或Nyberg-Rueppel(NR)签名示例)。

Crypto ++有一个基于ElGamal的密码系统。密码系统将在对称密钥下加密大块纯文本,然后在ElGamal密钥下加密对称密钥。我不确定它遵循什么标准(可能是IEEE的P1363)。请参阅elgamal.h中的SymmetricEncryptSymmetricDecrypt

密钥大小人为地小,因此程序运行得很快。 ElGamal是一个离散对数问题,因此其密钥大小在实践中应该是2048位或更高。 2048位受到ECRYPT(亚洲),ISO / IEC(全球),NESSIE(欧洲)和NIST(美国)的祝福。

如果您需要保存/保存/加载您生成的密钥,请参阅Crypto ++ wiki上的Keys and Formats。简短的回答是致电decryptor.Save()decryptor.Load();并远离{BER|DER}编码。

如果需要,您可以使用标准string而不是SecByteBlock。如果您有兴趣通过string和朋友将内容打印到终端,cout会更容易。

最后,现在有一个关于该主题的Crypto ++ Wiki页面,其中包含以下程序的源代码。请参阅Crypto ++的ElGamal Encryption

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;

#include <cryptopp/osrng.h>
using CryptoPP::AutoSeededRandomPool;

#include <cryptopp/secblock.h>
using CryptoPP::SecByteBlock;

#include <cryptopp/elgamal.h>
using CryptoPP::ElGamal;
using CryptoPP::ElGamalKeys;

#include <cryptopp/cryptlib.h>
using CryptoPP::DecodingResult;

int main(int argc, char* argv[])
{
    ////////////////////////////////////////////////
    // Generate keys
    AutoSeededRandomPool rng;

    cout << "Generating private key. This may take some time..." << endl;

    ElGamal::Decryptor decryptor;
    decryptor.AccessKey().GenerateRandomWithKeySize(rng, 512);
    const ElGamalKeys::PrivateKey& privateKey = decryptor.AccessKey();

    ElGamal::Encryptor encryptor(decryptor);
    const PublicKey& publicKey = encryptor.AccessKey();

    ////////////////////////////////////////////////
    // Secret to protect
    static const int SECRET_SIZE = 16;
    SecByteBlock plaintext( SECRET_SIZE );
    memset( plaintext, 'A', SECRET_SIZE );

    ////////////////////////////////////////////////
    // Encrypt

    // Now that there is a concrete object, we can validate
    assert( 0 != encryptor.FixedMaxPlaintextLength() );
    assert( plaintext.size() <= encryptor.FixedMaxPlaintextLength() );

    // Create cipher text space
    size_t ecl = encryptor.CiphertextLength( plaintext.size() );
    assert( 0 != ecl );
    SecByteBlock ciphertext( ecl );

    encryptor.Encrypt( rng, plaintext, plaintext.size(), ciphertext );

    ////////////////////////////////////////////////
    // Decrypt

    // Now that there is a concrete object, we can check sizes
    assert( 0 != decryptor.FixedCiphertextLength() );
    assert( ciphertext.size() <= decryptor.FixedCiphertextLength() );

    // Create recovered text space
    size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() );
    assert( 0 != dpl );
    SecByteBlock recovered( dpl );

    DecodingResult result = decryptor.Decrypt( rng, ciphertext, ciphertext.size(), recovered );

    // More sanity checks
    assert( result.isValidCoding );
    assert( result.messageLength <= decryptor.MaxPlaintextLength( ciphertext.size() ) );

    // At this point, we can set the size of the recovered
    //  data. Until decryption occurs (successfully), we
    //  only know its maximum size
    recovered.resize( result.messageLength );

    // SecByteBlock is overloaded for proper results below
    assert( plaintext == recovered );

    // If the assert fires, we won't get this far.
    if(plaintext == recovered)
        cout << "Recovered plain text" << endl;
    else
        cout << "Failed to recover plain text" << endl;

    return !(plaintext == recovered);
}

您也可以像Decryptor一样创建PrivateKey

ElGamalKeys::PrivateKey k;
k.GenerateRandomWithKeySize(rng, 512);
ElGamal::Decryptor d(k);
...

来自Encryptor的{​​{1}}:

PublicKey

您可以按如下方式在磁盘上保存和加载密钥:

ElGamalKeys::PublicKey pk;
privateKey.MakePublicKey(pk);
ElGamal::Encryptor e(pk);

密钥是ASN.1编码的,所以你可以像Peter Gutmann的ElGamalKeys::PrivateKey privateKey1; privateKey1.GenerateRandomWithKeySize(prng, 2048); privateKey1.Save(FileSink("elgamal.der", true /*binary*/).Ref()); ElGamalKeys::PrivateKey privateKey2; privateKey2.Load(FileSource("elgamal.der", true /*pump*/).Ref()); privateKey2.Validate(prng, 3); ElGamal::Decryptor decryptor(privateKey2); // ... 那样转储它们。

dumpasn1