首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ElGamal加密示例?

ElGamal加密示例?
EN

Stack Overflow用户
提问于 2013-11-14 10:02:10
回答 1查看 7.3K关注 0票数 3

我提前为n00bishness问了这个问题道歉,但我已经被困了很久了,我很难想出下一步该做什么。本质上,我试图对某些数据执行ElGamal加密。我得到了一个临时密钥对和第二个静态密钥的公共部分,以及一些数据。如果我的理解是正确的,这就是我执行加密所需的全部,但我很难弄清楚如何使用Crypto++。

我一直在寻找例子,但我可以在Google上找到真正的零。Ohloh没有多大帮助,因为我只是从密码ElGamal源文件中得到了无尽的页面,我似乎无法弄清楚这些文件(我对使用Crypto++还比较陌生,直到大约3天前还没有听说过ElGamal)。

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

代码语言:javascript
复制
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的时候只是个白痴。有人能帮我指出正确的方向吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-10 03:32:06

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

我们不能在这里帮助你,因为我们不知道该做什么。

临时密钥对可能用于模拟密钥交换,而静态密钥则是用于签署临时交换的长期密钥。除此之外,谁都不知道到底发生了什么。

你知道钥匙是什么吗?短期密钥是Diffie-Hellman密钥,静态密钥是ElGamal签名密钥吗?

如果我的理解是正确的,这就是我执行加密所需的全部,但我很难弄清楚如何使用Crypto++。

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

Crypto++有一个建立在ElGamal上的密码系统。密码系统将在对称密钥下加密一大块纯文本,然后对ElGamal密钥下的对称密钥进行加密。但我不确定它遵循了什么标准(很可能是IEEE的P1363)。参见SymmetricEncryptSymmetricDecrypt中的elgamal.h

键大小是人工小的,所以程序运行得很快。ElGamal是一个离散的日志问题,在实际中它的密钥大小应该是2048位或更高.2048年-bits由ECRYPT (亚洲)、ISO/IEC (全球)、NESSIE (欧洲)和NIST (美国)共同赞助。

如果您需要保存/持久化/加载您生成的键,那么请查看键和格式上的Crypto++ wiki。简单地说,就是打电话给decryptor.Save()decryptor.Load(),远离{BER|DER}编码。

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

最后,现在有一个关于Crypto++ Wiki的页面,用下面程序的源代码覆盖这个主题。参见Crypto++的ElGamal加密

代码语言:javascript
复制
#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

代码语言:javascript
复制
ElGamalKeys::PrivateKey k;
k.GenerateRandomWithKeySize(rng, 512);
ElGamal::Decryptor d(k);
...

和一个来自EncryptorPublicKey

代码语言:javascript
复制
ElGamalKeys::PublicKey pk;
privateKey.MakePublicKey(pk);
ElGamal::Encryptor e(pk);

您可以按以下方式将密钥保存到磁盘并从磁盘加载:

代码语言:javascript
复制
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);
// ...

密钥是ASN.1编码的,所以您可以使用像Peter的dumpasn1那样的方式转储它们

代码语言:javascript
复制
$ ./cryptopp-elgamal-keys.exe
Generating private key. This may take some time...
$ dumpasn1 elgamal.der 
  0 556: SEQUENCE {
  4 257:   INTEGER
       :     00 C0 8F 5A 29 88 82 8C 88 7D 00 AE 08 F0 37 AC
       :     FA F3 6B FC 4D B2 EF 5D 65 92 FD 39 98 04 C7 6D
       :     6D 74 F5 FA 84 8F 56 0C DD B4 96 B2 51 81 E3 A1
       :     75 F6 BE 82 46 67 92 F2 B3 EC 41 00 70 5C 45 BF
       :     40 A0 2C EC 15 49 AD 92 F1 3E 4D 06 E2 89 C6 5F
       :     0A 5A 88 32 3D BD 66 59 12 A1 CB 15 B1 72 FE F3
       :     2D 19 DD 07 DF A8 D6 4C B8 D0 AB 22 7C F2 79 4B
       :     6D 23 CE 40 EC FB DF B8 68 A4 8E 52 A9 9B 22 F1
       :             [ Another 129 bytes skipped ]
265   1:   INTEGER 3
268 257:   INTEGER
       :     00 BA 4D ED 20 E8 36 AC 01 F6 5C 9C DA 62 11 BB
       :     E9 71 D0 AB B7 E2 D3 61 37 E2 7B 5C B3 77 2C C9
       :     FC DE 43 70 AE AA 5A 3C 80 0A 2E B0 FA C9 18 E5
       :     1C 72 86 46 96 E9 9A 44 08 FF 43 62 95 BE D7 37
       :     F8 99 16 59 7D FA 3A 73 DD 0D C8 CA 19 B8 6D CA
       :     8D 8E 89 52 50 4E 3A 84 B3 17 BD 71 1A 1D 38 9E
       :     4A C4 04 F3 A2 1A F7 1F 34 F0 5A B9 CD B4 E2 7F
       :     8C 40 18 22 58 85 14 40 E0 BF 01 2D 52 B7 69 7B
       :             [ Another 129 bytes skipped ]
529  29:   INTEGER
       :     01 61 40 24 1F 48 00 4C 35 86 0B 9D 02 8C B8 90
       :     B1 56 CF BD A4 75 FE E2 8E 0B B3 66 08
       :   }

0 warnings, 0 errors.
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19974669

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档