【问题标题】:Extra data in result for AES/GCM decryptionAES/GCM 解密结果中的额外数据
【发布时间】:2015-06-16 14:54:30
【问题描述】:

我有以下代码,基本上是从 http://www.cryptopp.com/wiki/AuthenticatedDecryptionFilter 的 Crypto++ wiki 获取的

问题是,输出我得到“纯文本:abc1230000000077C8E390”而不是我所期望的,只是“纯文本:abc123”

最后的额外数据是什么?

还有两个基于相同代码库的小问题:

  1. 此方法是否可以作为使用 pdata 的实际随机字节数据的替代方法,或者因为它是字符串,所以它实际上必须像通常的文本一样?

  2. 我假设 adata 是以明文形式传输的,所以在存储密文时,我是否更正了 iv 和 adata 都是明文,并且用户只提供了密钥(用那些解密密文4 个元素:key(由用户提供)、ciphertext(可用)、iv(可用)和 adata(可用)?

谢谢!

AutoSeededRandomPool prng;

byte key[ AES::DEFAULT_KEYLENGTH ];
prng.GenerateBlock( key, sizeof(key) );

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

string adata( 16, (char)0x00 );

string cipherText = encryptData("abc123", adata, key, iv);
string plainText = decryptData(cipherText, adata, key, iv);
cout << "plaintext: " << plainText << endl;

//Utilities
string MainWindow::encryptData(string pdata, string adata, const byte *key, const byte *iv) {
    const int TAG_SIZE = 16;

    string cipher;

    try
        {
            GCM< AES >::Encryption e;
            e.SetKeyWithIV( key, AES::DEFAULT_KEYLENGTH, iv, AES::BLOCKSIZE );

            AuthenticatedEncryptionFilter ef( e,
                new StringSink( cipher ), false, TAG_SIZE
            ); // AuthenticatedEncryptionFilter

            ef.ChannelPut( "AAD", (const byte*)adata.data(), adata.size() );
            ef.ChannelMessageEnd("AAD");

            ef.ChannelPut( "", (const byte*)pdata.data(), pdata.size() );
            ef.ChannelMessageEnd("");
        }
        catch( CryptoPP::BufferedTransformation::NoChannelSupport& e )
        {
            cerr << "Caught NoChannelSupport..." << endl;
            cerr << e.what() << endl;
            cerr << endl;
        }
        catch( CryptoPP::AuthenticatedSymmetricCipher::BadState& e )
        {
            cerr << "Caught BadState..." << endl;
            cerr << e.what() << endl;
            cerr << endl;
        }
        catch( CryptoPP::InvalidArgument& e )
        {
            cerr << "Caught InvalidArgument..." << endl;
            cerr << e.what() << endl;
            cerr << endl;
        }

    return(cipher);
}

string MainWindow::decryptData(string cipher, string adata, const byte *key, const byte *iv) {
    const int TAG_SIZE = 16;
    string radata, rpdata;
    try
    {
        GCM< AES >::Decryption d;
        d.SetKeyWithIV( key, AES::DEFAULT_KEYLENGTH, iv, AES::BLOCKSIZE );

        string enc = cipher.substr( 0, cipher.length()-TAG_SIZE );
        string mac = cipher.substr( cipher.length()-TAG_SIZE );

        assert( cipher.size() == enc.size() + mac.size() );
        assert( enc.size() == pdata.size() );
        assert( TAG_SIZE == mac.size() );

        radata = adata;

        AuthenticatedDecryptionFilter df( d, NULL,
            AuthenticatedDecryptionFilter::MAC_AT_BEGIN |
            AuthenticatedDecryptionFilter::THROW_EXCEPTION, TAG_SIZE );

        df.ChannelPut( "", (const byte*)mac.data(), mac.size() );
        df.ChannelPut( "AAD", (const byte*)adata.data(), adata.size() );
        df.ChannelPut( "", (const byte*)enc.data(), enc.size() );

        df.ChannelMessageEnd( "AAD" );
        df.ChannelMessageEnd( "" );

        string retrieved;
        size_t n = (size_t)df.MaxRetrievable();
        retrieved.resize( n );

        if( n > 0 ) { df.Get( (byte*)retrieved.data(), n ); }
        rpdata = retrieved;
        assert( rpdata == pdata );

    }
    catch( CryptoPP::InvalidArgument& e )
    {
        cerr << "Caught InvalidArgument..." << endl;
        cerr << e.what() << endl;
        cerr << endl;
    }
    catch( CryptoPP::AuthenticatedSymmetricCipher::BadState& e )
    {
        cerr << "Caught BadState..." << endl;
        cerr << e.what() << endl;
        cerr << endl;
    }
    catch( CryptoPP::HashVerificationFilter::HashVerificationFailed& e )
    {
        cerr << "Caught HashVerificationFailed..." << endl;
        cerr << e.what() << endl;
        cerr << endl;
    }

    return rpdata;    
}

【问题讨论】:

    标签: c++ encryption aes crypto++


    【解决方案1】:

    问题是,输出我得到“明文:abc1230000000077C8E390”

    我的猜测是你重用了一个字符串。 Crypto++ 将在StringSink 中追加而不是覆盖。所以你得到了abc123,然后你设法以某种方式附加了0000000077C8E390


    以下内容对我有用。它是您程序的轻微修改版本。它使adatapdata 成为全局,重命名它们以避免名称隐藏,并通过pdata 传递消息。

    $ ./cryptopp-test.exe
    plaintext: Now is the time for all good men to come to the aide of their country
    
    $ ./cryptopp-test.exe wxyz
    plaintext: wxyz
    

    因为你使用的是THROW_EXCEPTION,所以你不需要这个:

    b = df.GetLastResult();
    assert( true == b );
    

    我认为数据应该以明文形式传输...

    是的。它可能类似于 IP 地址、磁盘扇区或计数器(等等)。

    更准确地说,它的数据仅经过身份验证。如果被篡改,就会被检测到。


    ...我是否正确的是 iv 和 adata 都是纯文本

    IV 可以是公共或私有参数。

    如果它是一个公共参数,那么它不需要被认证。它有点不直观,但那是因为篡改 IV 会篡改密码的状态,所以解密会失败,就好像你使用了错误的密钥一样。


    ...用户只提供密钥(用这4个元素解密密文:密钥(由用户提供),密文(可用),iv(可用)和adata(可用)?

    pdata 获得机密性和真实性保证;而adata 仅获得真实性保证。

    key 和 IV 是习惯性的。像往常一样处理它们(或应该这样做:)。


    using CryptoPP::DEFAULT_CHANNEL;
    using CryptoPP::AAD_CHANNEL;
    
    string encryptData(const string& pdata, const string& adata, const byte *key, unsigned int ksize, const byte *iv, unsigned int vsize);
    string decryptData(const string& cipher, const string& adata, const byte *key, unsigned int ksize, const byte *iv, unsigned int vsize);
    
    string xadata = "172.16.1.10";
    string xpdata = "Now is the time for all good men to come to the aide of their country";
    
    static const unsigned int TAG_SIZE = 16;
    
    int main(int argc, char* argv[])
    {
        (void)argc; (void)argv;
    
        if(argc >= 2)
            xpdata = argv[1];
    
        try {
    
            AutoSeededRandomPool prng;
    
            byte key[ AES::DEFAULT_KEYLENGTH ];
            prng.GenerateBlock( key, sizeof(key) );
    
            byte iv[ AES::BLOCKSIZE ];
            prng.GenerateBlock( iv, sizeof(iv) );
    
            string cipherText = encryptData(xpdata, xadata, key, sizeof(key), iv, sizeof(iv));
            string plainText = decryptData(cipherText, xadata, key, sizeof(key), iv, sizeof(iv));
    
            cout << "plaintext: " << plainText << endl;
        }
        catch(CryptoPP::Exception& ex)
        {
            cerr << ex.what() << endl;
        }
    
        return 0;
    }
    
    //Utilities
    string encryptData(const string& pdata, const string& adata, const byte *key, unsigned int ksize, const byte *iv, unsigned int vsize) {
    
        string cipher;
    
        GCM< AES >::Encryption e;
        e.SetKeyWithIV( key, ksize, iv, vsize );
    
        AuthenticatedEncryptionFilter ef( e,
                                         new StringSink( cipher ), false, TAG_SIZE
                                         ); // AuthenticatedEncryptionFilter
    
        ef.ChannelPut(AAD_CHANNEL, (const byte*)adata.data(), adata.size() );
        ef.ChannelMessageEnd(AAD_CHANNEL);
    
        ef.ChannelPut(DEFAULT_CHANNEL, (const byte*)pdata.data(), pdata.size() );
        ef.ChannelMessageEnd(DEFAULT_CHANNEL);
    
        return(cipher);
    }
    
    string decryptData(const string& cipher, const string& adata, const byte *key, unsigned int ksize, const byte *iv, unsigned int vsize) {
    
        string recovered;
    
        GCM< AES >::Decryption d;
        d.SetKeyWithIV( key, ksize, iv, vsize );
    
        const string& enc = cipher.substr( 0, cipher.length()-TAG_SIZE );
        const string& mac = cipher.substr( cipher.length()-TAG_SIZE );
    
        assert( cipher.size() == enc.size() + mac.size() );
        assert( enc.size() == xpdata.size() );
        assert( TAG_SIZE == mac.size() );
    
        AuthenticatedDecryptionFilter df( d, new StringSink(recovered),
                                         AuthenticatedDecryptionFilter::MAC_AT_BEGIN |
                                         AuthenticatedDecryptionFilter::THROW_EXCEPTION, TAG_SIZE );
    
        df.ChannelPut(DEFAULT_CHANNEL, (const byte*)mac.data(), mac.size() );
        df.ChannelPut(AAD_CHANNEL, (const byte*)adata.data(), adata.size() );
        df.ChannelPut(DEFAULT_CHANNEL, (const byte*)enc.data(), enc.size() );
    
        df.ChannelMessageEnd(AAD_CHANNEL);
        df.ChannelMessageEnd(DEFAULT_CHANNEL);
    
        assert( recovered == xpdata );        
        return(recovered);
    }
    

    【讨论】:

    猜你喜欢
    • 2017-05-17
    • 2015-03-27
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 2021-06-04
    • 1970-01-01
    • 2020-07-03
    相关资源
    最近更新 更多