HashVerificationFilter:消息散列或MAC无效有关修改后的GCM AE代码的错误

时间:2016-09-13 18:12:40

标签: exception encryption aes crypto++

我指的是CCM Mode上Crypto ++ wiki上的示例代码。我为测试目的做了一些修改,现在它正在抛出:

terminate called after throwing an instance of 'HashVerificationFilter::HashVerificationFailed'
what(): HashVerificationFilter: message hash or MAC not valid
Aborted (core dumped)

我见过'message hash or MAC not valid' exception after decryption。但我想传递字节数组而不是字符串,所以我认为我必须使用sizeof()运算符而不是size()。代码如下。

当传递密钥和iv时,sizeof函数将其大小设为8而不是16字节。

错误是因为AuthenticatedDecryptionFilter::DEFAULT_FLAGS吗?

以下是代码:

#include <iostream>
#include <cstdio>
//#include "libcryptoWrapperGCM.h"
using std::cout;
using std::endl;
using std::cerr;

#include <string>
#include <stdint.h>
using std::string;

#include "hex.h"
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;

#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;

#include "cryptlib.h"
using CryptoPP::BufferedTransformation;
using CryptoPP::AuthenticatedSymmetricCipher;

#include "filters.h"
using CryptoPP::Redirector;
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::AuthenticatedEncryptionFilter;
using CryptoPP::AuthenticatedDecryptionFilter;

#include "aes.h"
using CryptoPP::AES;

#include "gcm.h"
using CryptoPP::GCM;

#include "assert.h"

void GCM_Encode(byte key[], byte iv[], string pdata, string cipher, const int TAG_SIZE)
    {

        // Encrypted, with Tag
        string encoded;

        cout << "key size= " << sizeof(key) << endl;
        cout << "IV size= " << sizeof(iv) << endl;

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

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

            StringSource ss1( pdata, true,
                new AuthenticatedEncryptionFilter( e,
                    new StringSink( cipher ), false, TAG_SIZE
                ) // AuthenticatedEncryptionFilter
            ); // StringSource

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

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

void GCM_Decode(byte key[], byte iv[], string cipher, string rpdata, const int TAG_SIZE)
    {
        try
        {
            GCM< AES >::Decryption d;
            d.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );

            AuthenticatedDecryptionFilter df( d,
                new StringSink( rpdata ),
                AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE
            ); // AuthenticatedDecryptionFilter

            // The StringSource dtor will be called immediately
            //  after construction below. This will cause the
            //  destruction of objects it owns. To stop the
            //  behavior so we can get the decoding result from
            //  the DecryptionFilter, we must use a redirector
            //  or manually Put(...) into the filter without
            //  using a StringSource.
            StringSource ss2( cipher, true,
                new Redirector( df /*, PASS_EVERYTHING */ )
            ); // StringSource

            // If the object does not throw, here's the only
            //  opportunity to check the data's integrity
            if( true == df.GetLastResult() ) {
                cout << "recovered text: " << rpdata << endl;
            }
        }
        catch( CryptoPP::Exception& e )
        {
            cerr << e.what() << endl;
            exit(1);
        }

    }

int main()
{
    byte key[]= {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
    byte iv[] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
    string pdata = "Authenticated Encryption";
    const int TAG_SIZE = 12;
    string rpdata, cipher;

    //void GCM_Encode(byte key[], byte iv[],  string pdata, string cipher, const int TAG_SIZE)
    GCM_Encode( key, iv, pdata, cipher, TAG_SIZE);
    cout << "======INT MAIN======" << endl;
    cout << "Encryption complete" << endl;
    cout << "cipher= " << cipher << endl; 


    //void GCM_Decode(byte key[], byte iv[], string cipher, string rpdata, const int TAG_SIZE)
    GCM_Decode( key, iv, cipher, rpdata, TAG_SIZE);
    cout << "Decryption complete" << endl;
    cout << "rpdata= " << rpdata << endl;

    return 0;
}

GDB输出是,

Encryption complete
cipher= 
HashVerificationFilter: message hash or MAC not valid
[Inferior 1 (process 16632) exited with code 01]

编译命令

g++ -g3 -O3 -fPIC GCM_Test2.cpp -o GCMTest3 -lcryptopp -pthread -lrt -lc

包含使用添加的路径,

export CPLUS_INCLUDE_PATH=/usr/local/include/cryptopp

locate raise.c

上没有输出

1 个答案:

答案 0 :(得分:1)

问题是GCM_Encode这两个函数都解释了密钥和iv的错误大小。

cout << "sizeof(key)= " << sizeof(key) << endl;
cout << "sizeof(iv)= " << sizeof(iv) << endl;

是8而不是16.所以想法是将它转换为字符串并使用.size()获取其大小

std::string key1( reinterpret_cast<char const*>(key), sizeof(key) )
std::string iv1( reinterpret_cast<char const*>(iv), sizeof(iv) )

但请记住向SetKeyWithIV函数提供原始字节数组,因为它不接受字符串作为其参数。

e.SetKeyWithIV( key, key1.size(), iv, iv1.size() )