0

I am using this solved post as a reference but cannot seem to get the same result: AES128 in libgcrypt not encrypting

When I print the string to console, I get junk characters. I think it may be due to '\0' being in the string but I am not certain how to go about that.

//aes.cpp

#include "aes.h"
#include <iostream>
#include <stdio.h>

#define GCRY_CIPHER GCRY_CIPHER_AES128   // Pick the cipher here
#define GCRY_MODE GCRY_CIPHER_MODE_ECB // Pick the cipher mode here

aes::aes(std::string k)
{
    key_ = k;
    keyLength_ = gcry_cipher_get_algo_keylen(GCRY_CIPHER);

    gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    gcry_cipher_open(&handle, GCRY_CIPHER, GCRY_MODE, 0);
    gcry_cipher_setkey(handle, key_.c_str(), keyLength_);
}

void aes::encrypt(string text, std::vector<char>& ret) {
    size_t textLength = text.size() + 1;
    ret.resize(textLength);
    gcry_cipher_encrypt(handle, ret.data(), textLength, text.c_str(), textLength);
}

string aes::decrypt(std::vector<char> const& text) {
    size_t textLength = text.size() + 1;


    char * decBuffer = new char[textLength];
    gcry_cipher_decrypt(handle, decBuffer, textLength, text.data(), textLength);
    string ret (decBuffer);
    delete [] decBuffer;
    return ret;
}

//aes.h

#include <gcrypt.h>
#include <iostream>

#ifndef AES_H
#define AES_H

class aes
{
public:
    aes(std::string);
    ~aes();

    gcry_cipher_hd_t handle;
    void encrypt(std::string, std::vector<char>&);
    std::string decrypt(std::vector<char> const&); 

private:
    std::string key_;
    size_t keyLength_; 
};

#endif // AES_H

//main.cpp

#include "aes.h"
#include <iostream>

int main()
{
    std::vector<char> data;

    aes bb = aes("one test AES key");
    bb.encrypt("Some message", data);

    std::string dec = bb.decrypt(data);
    std::cout << "decrypted string " << dec << std::endl;
    return 0;
    //output gives me: decrypted string �

}
KS7X
  • 332
  • 2
  • 15
  • `gcry_cipher_decrypt` doesn't return in some way the length of the decrypted string? – PaulMcKenzie Dec 12 '18 at 19:32
  • @PaulMcKenzie `gcry_cipher_decrypt` returns a `0` on success or an error code – KS7X Dec 12 '18 at 19:35
  • [Possible duplicate](https://stackoverflow.com/questions/28845263/determine-size-of-decrypted-data-from-gcry-cipher-decrypt). Once you know the size, the string you construct should be `string ret(decBuffer, size);` and not just `string ret(decBuffer);` – PaulMcKenzie Dec 12 '18 at 19:36
  • I checked if there was an error code to return. I get `gcry_cipher_decrypt failed: gcrypt/Invalid length` – KS7X Dec 12 '18 at 19:50
  • What are `GCRY_CIPHER` and `GCRY_MODE`? – David Schwartz Dec 12 '18 at 19:52
  • @DavidSchwartz forgot to paste those in. Edited post – KS7X Dec 12 '18 at 19:54

1 Answers1

2

For AES128 in ECB mode, the size of the data to be encrypted must be a multiple of 128 bits. The plaintext and ciphertext sizes must be precisely the same.

Here's working code to give you an idea of what you need to do to make it work. But I'd strongly suggest you rethink using ECB.

#include <gcrypt.h>
#include <iostream>
#include <vector>
#include <stdio.h>

class aes
{
public:
    aes(std::string);
    ~aes() { ; }

    gcry_cipher_hd_t handle;
    void encrypt(std::string, std::vector<char>&);
    std::string decrypt(std::vector<char> const&); 

private:
    std::string key_;
    size_t keyLength_; 
};

#define GCRY_CIPHER GCRY_CIPHER_AES128
#define GCRY_MODE GCRY_CIPHER_MODE_ECB

aes::aes(std::string k)
{
    key_ = k;
    keyLength_ = gcry_cipher_get_algo_keylen(GCRY_CIPHER);

    gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    gcry_cipher_open(&handle, GCRY_CIPHER, GCRY_MODE, 0);
    gcry_cipher_setkey(handle, key_.c_str(), keyLength_);
}

void aes::encrypt(std::string text, std::vector<char>& ret)
{

    // round up to the nearest multiple of the AES block size
    while ((text.size() & 0xf) != 0xf)
        text += " ";

    size_t textLength = text.size() + 1;
    ret.resize(textLength);
    int err = gcry_cipher_encrypt(handle, ret.data(), textLength, text.c_str(), textLength);
    if (err != 0)
    {
       std::cout << "encrypt fail" <<
           gcry_strsource(err) << " " <<
           gcry_strerror(err) << std::endl;
    }
}

std::string aes::decrypt(std::vector<char> const& text) {
    size_t textLength = text.size();

    char * decBuffer = new char[textLength];

    int err=gcry_cipher_decrypt(handle, decBuffer, textLength, text.data(), textLength);
    if (err != 0)
    {
       std::cout << "decrypt fail: " <<
           gcry_strsource(err) <<  " " <<
           gcry_strerror(err) << std::endl;
     }

    std::string ret (decBuffer);
    delete [] decBuffer;
    return ret;
}

int main()
{
    std::vector<char> data;

    aes bb = aes("one test AES key");
    bb.encrypt("Some message", data);


    std::string dec = bb.decrypt(data);
    std::cout << "decrypted string " << dec << std::endl;
    return 0;
}

decrypted string Some message

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I missed that detail when it comes to encrypting and decrypting. Changing the size of my buffer to a multiple of 16 bytes solved the problem. Thanks for pointing that out for me. I will take a look at the other modes to see if something else better suits my project. – KS7X Dec 12 '18 at 20:18
  • @KS7X ECB is almost never the right choice. It's like a linked list -- you learn it first, but it's almost never the right thing to actually use. (I'm going to get lots of angry comments from linked list fans for that, aren't I?) – David Schwartz Dec 12 '18 at 20:29