4

我试图弄清楚如何使用 AES 解密一个密文块。我正在使用 crypto++ 库 - 或者至少尝试使用该库。但我绝对无处可去。我假设运行这个解密算法只需要几行代码,但我想不通。这就是我写的。现在开始大笑:

#include <stdio.h>
#include <cstdlib>
#include <rijndael.h>
#include <sha.h>

using namespace std;

int main()
{

    // Decryption
    CTR_Mode< AES >::Decryption decryptor;
    decryptor.SetKeyWithIV( cbcKey, AES::DEFAULT_KEYLENGTH, cbcCipher );
}

谁能给我一个简短的教程,告诉我如何“简单地”解密一个 16 字节的密文块,给定一个使用 crypto++ 的解密密钥?他们的文档比您在上面看到的密文(至少对我而言)更神秘,而且我通过搜索几乎找不到帮助。非常感谢。

4

4 回答 4

1

谁能给我一个简短的教程,告诉我如何“简单地”解密一个 16 字节的密文块,给定一个使用 crypto++ 的解密密钥?

这来自 Crypto++ wiki。它提供了一个CTR 模式示例

AutoSeededRandomPool prng;

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

byte ctr[ AES::BLOCKSIZE ];
prng.GenerateBlock( ctr, sizeof(ctr) );

string plain = "CTR Mode Test";
string cipher, encoded, recovered;

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

try
{
    cout << "plain text: " << plain << endl;

    CTR_Mode< AES >::Encryption e;
    e.SetKeyWithIV( key, key.size(), ctr );

    // The StreamTransformationFilter adds padding
    //  as required. ECB and CBC Mode must be padded
    //  to the block size of the cipher. CTR does not.
    StringSource ss1( plain, true, 
        new StreamTransformationFilter( e,
            new StringSink( cipher )
        ) // StreamTransformationFilter      
    ); // StringSource
}
catch( CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

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

// Pretty print cipher text
StringSource ss2( cipher, true,
    new HexEncoder(
        new StringSink( encoded )
    ) // HexEncoder
); // StringSource
cout << "cipher text: " << encoded << endl;

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

try
{
    CTR_Mode< AES >::Decryption d;
    d.SetKeyWithIV( key, key.size(), ctr );

    // The StreamTransformationFilter removes
    //  padding as required.
    StringSource ss3( cipher, true, 
        new StreamTransformationFilter( d,
            new StringSink( recovered )
        ) // StreamTransformationFilter
    ); // StringSource

    cout << "recovered text: " << recovered << endl;
}
catch( CryptoPP::Exception& e )
{
    cerr << e.what() << endl;
    exit(1);
}

下面是运行示例程序的结果:

$ ./crytpopp-test.exe 
key: F534FC7F0565A8CF1629F01DB31AE3CA
counter: A4D16CBC010DACAA2E54FA676B57A345
plain text: CTR Mode Test
cipher text: 12455EDB41020E6D751F207EE6
recovered text: CTR Mode Test
于 2013-10-04T04:49:58.250 回答
1

crypto++ 库网页上的常见问题解答包含指向“教程”的指针,去那里阅读吧。

于 2012-07-01T06:58:22.980 回答
0

事实上,Crypto++ 教程非常难学。一般来说,要使用 Crypto++ API,您至少需要具备一些密码学的基本知识,我建议您参加Cryptography course

说了这么多,我来回答你的问题。由于它有点模棱两可,我假设您想使用 CTR 模式解密 AES 密码。作为输入,假设您有一个密码、IV 和密钥(均以 a 中的十六进制表示std::string)。

#include <iostream>
#include <string>

#include "crypto++/modes.h" // For CTR_Mode
#include "crypto++/filters.h" //For StringSource
#include "crypto++/aes.h" // For AES
#include "crypto++/hex.h" // For HexDecoder

int main(int argc, char* argv[]) {
    // Our input:
    // Note: the input was previously generated by the same cipher 
    std::string iv_string = "37C6D22FADE22B2D924598BEE2455EFC";
    std::string cipher_string = "221DF9130F0E05E7E87C89EE6A";
    std::string key_string = "7D9BB722DA2DC8674E08C3D44AAE976F";

    std::cout << "Cipher text: " << cipher_string << std::endl;
    std::cout << "Key: " << key_string << std::endl;
    std::cout << "IV: " << iv_string << std::endl;

    // 1. Decode iv: 
    // At the moment our input is encoded in string format...
    // we need it in raw hex: 
    byte iv[CryptoPP::AES::BLOCKSIZE] = {};
    // this decoder would transform our std::string into raw hex:
    CryptoPP::HexDecoder decoder;
    decoder.Put((byte*)iv_string.data(), iv_string.size());
    decoder.MessageEnd();
    decoder.Get(iv, sizeof(iv));

    // 2. Decode cipher:
    // Next, we do a similar trick for cipher, only here we would leave raw hex
    //  in a std::string.data(), since it is convenient for us to pass this
    // std::string to the decryptor mechanism:
    std::string cipher_raw;
    {
        CryptoPP::HexDecoder decoder;
        decoder.Put((byte*)cipher_string.data(), cipher_string.size());
        decoder.MessageEnd();

        long long size = decoder.MaxRetrievable();
        cipher_raw.resize(size);       
        decoder.Get((byte*)cipher_raw.data(), cipher_raw.size());
        // If we print this string it's completely rubbish: 
        // std::cout << "Raw cipher: " << cipher_raw << std::endl;
    }

    // 3. Decode the key:
    // And finally the same for the key:
    byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
    {
        CryptoPP::HexDecoder decoder;
        decoder.Put((byte*)key_string.data(), key_string.size());
        decoder.MessageEnd();
        decoder.Get(key, sizeof(key));
    }

    // 4. Decrypt:
    std::string decrypted_text;
    try {
            CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption d;
            d.SetKeyWithIV(key, sizeof(key), iv);

            CryptoPP::StringSource ss(
                cipher_raw, 
                true, 
                new CryptoPP::StreamTransformationFilter(
                    d,
                    new CryptoPP::StringSink(decrypted_text)
                ) // StreamTransformationFilter
            ); // StringSource

            std::cout << "Decrypted text: " << decrypted_text << std::endl;
    }
    catch( CryptoPP::Exception& e ) {
            std::cerr << e.what() << std::endl;
            exit(1);
    }

    return 0;
}

我使用 Crypto++562 在 Ubutunu 14.04 上编译它:

g++ -Wall -std=c++0x -o prog practicalAES.cpp -lcryptopp

如果我运行程序,我会得到以下输出:

Cipher text: 221DF9130F0E05E7E87C89EE6A Key: 7D9BB722DA2DC8674E08C3D44AAE976F IV: 37C6D22FADE22B2D924598BEE2455EFC Decrypted text: CTR Mode Test

它在这里并不真正可见,但 Key 和 IV 具有相同的长度 - 16 个字节(或 128 位)。这是块大小,所以这个密码是 AES-128。由于是CTR方式,所以不加padding,密文和明文的字节数相同。

另请注意,60% 的代码涉及将字符串解码为十六进制,而解密本身只是最后一步(因此,如果您的输入数据是原始十六进制,则不需要解码)。

于 2014-10-02T14:49:15.910 回答
0

Crypto++ 的教程侧重于过滤器以及源和接收器的使用,在我看来,它们过于复杂。在您的情况下,代码实际上非常简单:

CTR_Mode< AES >::Decryption decryptor;
decryptor.SetKeyWithIV( cbcKey, AES::DEFAULT_KEYLENGTH, cbcCipher );
decryptor.ProcessData(output, input, size);

// Decrypt another piece of data with the same key
decryptor.Resynchronize(new_iv, new_iv_length);
decryptor.ProcessData(new_output, new_input, size);
于 2017-01-29T15:15:35.857 回答