0

First of all, I am a beginner to C ++

i try to encrypt and decrypt data in c++ with crypto++ library

and i create custom class for this

class:

#ifndef CRYPTODATA
#define CRYPTODATA
typedef unsigned char byte;
#include <iostream>
#include "stdafx.h"
#include "assert.h"
using std::cerr;
using std::cout;
#include "cryptopp/hex.h"
using CryptoPP::HexDecoder;
using CryptoPP::HexEncoder;

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

#include <string>
using std::string;

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

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

#include "cryptopp/gcm.h"
using CryptoPP::GCM;
using CryptoPP::GCM_TablesOption;
#include <string>
namespace CryptoData{
    class CryptoData{
    public:
        CryptoData(){
      
            std::string _key = "mohsensalamkojayikhoobikhosshhaa";
            std::string _iv = "mohsensalamk";
            std::copy(_key.begin(), _key.end(), this->key);
            std::copy(_iv.begin(), _iv.end(), this->iv);
            pad = (16, (char)0x00);
           
        }
        CryptoData(std::string _key, std::string _iv, std::string _pad):pad(_pad){
            std::copy(_key.begin(), _key.end(), this->key);
            std::copy(_iv.begin(), _iv.end(), this->iv);
            std::copy(_pad.begin(), _pad.end(), this->pad);
        }
        ~CryptoData() {

        }   
        std::string _encrypting(std::string _data){
            return this->encryptData(_data);
        }
        std::string _decrypting(std::string _data) {
            return this->decryptData(_data);
        }
        
    
    protected:
        std::string decryptData(std::string _data) {
            std::string radata, rpdata;
            try
            {
                GCM<AES>::Decryption d;
                d.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
                
                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() == pad.size());
                assert(TAG_SIZE == mac.size());
                radata = _data;
                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*)_data.data(), _data.size());
                df.ChannelPut("", (const byte*)enc.data(), enc.size());
                df.ChannelMessageEnd("AAD");
                df.ChannelMessageEnd("");
                bool b = false;
                b = df.GetLastResult();
                assert(true == b);

                string retrieved;
                size_t n = (size_t)-1;

                df.SetRetrievalChannel("");
                n = (size_t)df.MaxRetrievable();
                retrieved.resize(n);

                if (n > 0)
                {
                    df.Get((byte*)retrieved.data(), n);
                }
                rpdata = retrieved;
                printf("done6 \n");
                assert(rpdata == pad);

                cout << "its a decrypted data " << radata << " \n";
            }
            catch (CryptoPP::InvalidArgument& e)
            {
                cerr << "Caught InvalidArgument..." << endl;
            }
            catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
            {
                cerr << "Caught BadState..." << endl;
            }
            catch (CryptoPP::HashVerificationFilter::HashVerificationFailed& e)
            {
                cerr << "Caught HashVerificationFailed..." << endl;
                cerr << e.what() << endl;
            }
            return radata;
        }
        std::string encryptData(std::string _data){
            std::string encoded;
            try
            {    
                GCM<AES>::Encryption e;
                e.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

                AuthenticatedEncryptionFilter ef(e,
                    new StringSink(cipher), false, TAG_SIZE); // AuthenticatedEncryptionFilter
               
                ef.ChannelPut("AAD", (const byte*)_data.data(), _data.size());
                ef.ChannelMessageEnd("AAD");

                ef.ChannelPut("", (const byte*)pad.data(), pad.size());
                ef.ChannelMessageEnd("");
                
                // Pretty print
                StringSource(cipher, true,
                    new HexEncoder(new StringSink(encoded), true, 16, " "));
            }
            catch (CryptoPP::BufferedTransformation::NoChannelSupport& e)
            {
                cerr << "Caught NoChannelSupport..." << endl;
            }
            catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
            {
                cerr << "Caught BadState..." << endl;
            }
            catch (CryptoPP::InvalidArgument& e)
            {
                cerr << "Caught InvalidArgument..." << endl;
              
            }
            return encoded;
        }
    private:
        byte key[32];
        byte iv[12];
        const int TAG_SIZE = 16;
        std::string cipher;
        std::string pad;
    };
}
#endif

I try to encrypt and decrypt the String with the following code:

int __cdecl main(void)
{
    CryptoData::CryptoData crypt;
    std::string _myData = "mohsenjooooon:X";
    std::string _encrypted = crypt._encrypting(_myData);
    printf("its encrypted data: %p  \n", _encrypted);
    std::string _decData = crypt._decrypting(_encrypted);
    printf("its decrypted data: %p \n", _decData);
    return 0;

}

and finally i get this Exception:

Caught HashVerificationFailed... HashVerificationFilter: message hash or MAC not valid

Thanks for the help, where is my code problem?

Mohsen Haydari
  • 550
  • 5
  • 20
  • Does this answer your question? [HashVerificationFilter: message hash or MAC not valid Error on modified GCM AE code](https://stackoverflow.com/questions/30936448/message-hash-or-mac-not-valid-exception-after-decryption) – Devolus Feb 03 '21 at 10:15
  • 1
    `delete &key;` - no, no, no, no, no. No. You need to learn the basics. Get [a good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – molbdnilo Feb 03 '21 at 10:16
  • @Devolus hey , thank for your answer but no – Mohsen Haydari Feb 03 '21 at 10:19
  • @molbdnilo why no ? here i dont call destractur!! – Mohsen Haydari Feb 03 '21 at 10:23
  • @MrHaydari I have no idea what you mean by that comment. What gave you the idea that you should `delete` member variables, or anything at all that you didn't create with `new`? – molbdnilo Feb 03 '21 at 10:29
  • @molbdnilo thanks man for your answer, im new in c++, I mean the previous comment i dont ask question why i get exception Memory not found, i ask question why decrypt and encrypt not working :) – Mohsen Haydari Feb 03 '21 at 10:40
  • More basic problems: `pad = (16, (char)0x00);` is equivalent to `pad = (char)0x00;` and makes `pad` the empty string. Read about initialization, assignment, and the comma operator in a good C++ book. – molbdnilo Feb 03 '21 at 12:11
  • @molbdnilo thanks, i create pad with empty string 16 char(byte) for auth and important here for me is a size of a pad , the problem with the program was that i put wrong data to differents channel, and fixed, thanks ! – Mohsen Haydari Feb 03 '21 at 12:52
  • @MrHaydari You did not create a pad with 16 characters - it contains no characters at all. `pad = std::string(16, 0);` would make a string with 16 null characters. But why not use a 16-character array? – molbdnilo Feb 03 '21 at 13:00
  • @molbdnilo here pad = (16, (char)0x00); i wanted to create 16 byte space/null or anything for put to channel and did not care about the data inside,although my work was wrong and the variable should be declared like this String pad(16, (char)0x00); and you are exactly right, Thank you for introducing the book and I will definitely read it, can I have your account on social media or github? – Mohsen Haydari Feb 03 '21 at 13:25

1 Answers1

1

i put wrong data to wrong channel

fixed:

#ifndef CRYPTODATA
#define CRYPTODATA
typedef unsigned char byte;
#include <iostream>
#include "stdafx.h"
#include "assert.h"
using std::cerr;
using std::cout;
#include "cryptopp/hex.h"
using CryptoPP::HexDecoder;
using CryptoPP::HexEncoder;

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

#include <string>
using std::string;

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

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

#include "cryptopp/gcm.h"
using CryptoPP::GCM;
using CryptoPP::GCM_TablesOption;
#include <string>
namespace CryptoData{
    class CryptoData{
    public:
        CryptoData(){
      
            std::string _key = ":D:D:D:D:D:D:D:D::D:D:D:";
            std::string _iv = ":D:D::D:D:D:D:";
            std::copy(_key.begin(), _key.end(), this->key);
            std::copy(_iv.begin(), _iv.end(), this->iv);
            string pad(16, (char)0x00);
            authCode = pad;
            printf("default constractor call \n");
           
        }
        CryptoData(std::string _key, std::string _iv, std::string _pad):authCode(_pad){
            std::copy(_key.begin(), _key.end(), this->key);
            std::copy(_iv.begin(), _iv.end(), this->iv);
            printf("constractor call with args \n");
        }
        ~CryptoData() {
            printf("default destractur call \n");

        }   
        std::string _encrypting(std::string _data){
            return this->encryptData(_data);
        }
 
        std::string _decrypting(std::string _data) {
            return this->decryptData(_data);
        }
       
    
    protected:
        std::string decryptData(std::string _data) {
            std::string radata, rpdata;
            try
            {
                GCM<AES>::Decryption d;
                d.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
                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() == _data.size());
                assert(TAG_SIZE == mac.size());
                radata = authCode;
                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*)authCode.data(), authCode.size());

                df.ChannelPut("", (const byte*)enc.data(), enc.size());
                df.ChannelMessageEnd("AAD");
                df.ChannelMessageEnd("");
                bool b = false;
                b = df.GetLastResult();
                assert(true == b);

                string retrieved;
                size_t n = (size_t)-1;

                df.SetRetrievalChannel("");
                n = (size_t)df.MaxRetrievable();
                retrieved.resize(n);

                if (n > 0)
                {
                    df.Get((byte*)retrieved.data(), n);
                }
                rpdata = retrieved;
                printf("done6 \n");
                //assert(rpdata == pad);

                cout << "its a decrypted data " << radata << " \n";
            }
            catch (CryptoPP::InvalidArgument& e)
            {
                cerr << "Caught InvalidArgument..." << endl;
            }
            catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
            {
                cerr << "Caught BadState..." << endl;
            }
            catch (CryptoPP::HashVerificationFilter::HashVerificationFailed& e)
            {
                cerr << "Caught HashVerificationFailed..." << endl;
                cerr << e.what() << endl;
            }
            return rpdata;
        }
        
        std::string encryptData(std::string _data){
            std::string encoded;
            try
            {    
                GCM<AES>::Encryption e;
                e.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

                AuthenticatedEncryptionFilter ef(e,
                    new StringSink(cipher), false, TAG_SIZE); // AuthenticatedEncryptionFilter
               
                ef.ChannelPut("AAD", (const byte*)authCode.data(), authCode.size());
                ef.ChannelMessageEnd("AAD");

                ef.ChannelPut("", (const byte*)_data.data(), _data.size());
                ef.ChannelMessageEnd("");
                
                // Pretty print
                StringSource(cipher, true,
                    new HexEncoder(new StringSink(encoded), true, 16, " "));
            }
            catch (CryptoPP::BufferedTransformation::NoChannelSupport& e)
            {
                cerr << "Caught NoChannelSupport..." << endl;
            }
            catch (CryptoPP::AuthenticatedSymmetricCipher::BadState& e)
            {
                cerr << "Caught BadState..." << endl;
            }
            catch (CryptoPP::InvalidArgument& e)
            {
                cerr << "Caught InvalidArgument..." << endl;
              
            }
            return encoded;
        }
    private:
        byte key[32];
        byte iv[12];
        const int TAG_SIZE = 16;
        std::string cipher;
        std::string authCode;
    };
}
#endif

Mohsen Haydari
  • 550
  • 5
  • 20