【问题标题】:HashVerificationFilter: message hash or MAC not valid Error on modified GCM AE codeHashVerificationFilter:消息哈希或 MAC 无效 修改 GCM AE 代码上的错误
【发布时间】:2016-09-15 13:58:34
【问题描述】:

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

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 没有输出

【问题讨论】:

  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行逐行检查您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • “我为测试目的做了一些修改,现在它正在抛出......” - 当你得到一个因修改而破坏的已知商品时,通常习惯于改变一次隔离一件事。此外,您引用了 CCM 模式页面,但提供了 GCM 模式代码。不要试图混合/匹配它们。

标签: exception encryption aes crypto++


【解决方案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() )

【讨论】:

  • byte key[] 是一个指针,而不是一个数组。这是错误的,因为如果嵌入了 NULL 字符,它将失败:reinterpret_cast&lt;char const*&gt;(key), sizeof(key)。为工作使用正确的 API:GCM_Encode(const byte key[], unsigned int ksize, ...)。然后,string key( reinterpret_cast&lt;char*&gt;(key), ksize ); 它也更高效,因为它避免了创建临时字符串。
猜你喜欢
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多