Encryption and Decryption with OpenSSL - cryptinfo class!

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Dreadstew
Posts: 23
Joined: Wed Apr 01, 2015 5:18 pm

Encryption and Decryption with OpenSSL - cryptinfo class!

Post by Dreadstew »

Code: Select all

#pragma once
#include <GoldenAge/debug.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <string>
 
namespace ga {
    class cryptinfo {
        EVP_CIPHER_CTX* ectx;
        EVP_CIPHER_CTX* dctx;
 
        void fillectx()
        {
            debug("making new encryption ctx");
            if (!(ectx = EVP_CIPHER_CTX_new())) handleErrors();
            debug("setting ctx encryption engine to EVP_aes_256_cbc()");
            if (1 != EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, NULL, NULL)) handleErrors();
            debug("initializing ctx with key and iv", key, " ", iv);
            if (1 != EVP_EncryptInit_ex(ectx, NULL, NULL, key, iv)) handleErrors();
            debug("making new encryption ctx good");
        }
 
        void filldctx()
        {
            debug("making new decryption ctx");
            if (!(dctx = EVP_CIPHER_CTX_new())) handleErrors();
            debug("setting ctx decryption engine to EVP_aes_256_cbc()");
            if (!EVP_DecryptInit_ex(dctx, EVP_aes_256_cbc(), NULL, NULL, NULL)) handleErrors();
            debug("initializing ctx with key and iv");
            if (!EVP_DecryptInit_ex(dctx, NULL, NULL, key, iv)) handleErrors();
            debug("making new decryption ctx good");
        }
 
        void filldectx()
        {
            debug("make both encryption and decryption ctx at the same time");
            fillectx();
            filldctx();
            debug("make both good");
        }
 
        void handleErrors(void)
        {
            unsigned long errCode;
            debug("An error has occured in encryption/decryption");
            while (errCode = ERR_get_error())
                debug(ERR_error_string(errCode, NULL));
            debug("should we really exit here?");
            system("pause");
            abort();
        }
    
        friend char* operator<<(char* os, cryptinfo  &e);
        friend char* operator>>(char* os, cryptinfo  &e);
        friend std::ostream& operator<<(std::ostream &os, const  cryptinfo  &e);
        friend std::istream& operator>>(std::istream &os, cryptinfo  &e);
 
    public:
        uint8_t key[33];
        uint8_t iv[AES_BLOCK_SIZE + 1];
 
        void fillkeyiv()
        {
            debug("creating new key and iv for a cryptinfo");
            debug("creating key");
            RAND_bytes(key, sizeof(key) -  1);
            key[32] = '\0'; //always null terminate our data so we can toString() (hope that works out lol)
            debug("creating iv");
            RAND_bytes(iv, sizeof(iv) - 1);
            iv[16] = '\0';
            debug("creating new key and iv good");
        }
 
        int encrypt(std::string& encrypt_in, std::string& encrypt_out, unsigned char* aad = 0, int aad_len = 0)
        {
            debug("encrypt called");
            fillectx();
            debug("encrypting string ", encrypt_in);
            int len;
            int ciphertextlen;
            unsigned char encrypt_in_buf[48];
            debug("writing encrypted bytes to ciphertext");
            if (1 != EVP_EncryptUpdate(ectx, encrypt_in_buf, &len, (const unsigned char*)encrypt_in.c_str(), encrypt_in.size())) handleErrors();
            ciphertextlen = len;
            debug("writing final bytes to ciphertext");
            if (1 != EVP_EncryptFinal_ex(ectx, encrypt_in_buf + ciphertextlen, &len)) handleErrors();
            ciphertextlen += len;
            encrypt_in_buf[ciphertextlen] = '\0';
            debug("free ctx obj");
            EVP_CIPHER_CTX_free(ectx);
            encrypt_out = (const char*)encrypt_in_buf;
            debug("encrypted string ", encrypt_out);
            debug("encrypt good");
            return ciphertextlen;
        }
 
        int decrypt(std::string& ciphertext, std::string& plainstr, unsigned char *aad = 0, int aad_len = 0)
        {
            debug("decrypt called");
            filldctx();
            debug("decrypting string ", ciphertext);
            unsigned char buf[48];
            debug("writing unencrypted bytes to plaintext");
            int len;
            if (!EVP_DecryptUpdate(dctx, buf, &len, (const unsigned char*)ciphertext.c_str(), ciphertext.size())) handleErrors();
            debug("writing final bytes to plaintext");
            int oldlen = len;
            int ret = EVP_DecryptFinal_ex(dctx, buf + oldlen, &len);
            oldlen += len;
            buf[oldlen] = '\0';
            debug("freeing ctx obj");
            EVP_CIPHER_CTX_free(dctx);
            plainstr = (const char*)buf;
            debug("the decrypted string ", plainstr);
            if (ret == 1)
            {
                debug("decryption good");
                return oldlen;
            }
            else
            {
                debug("EVP Decryption Error! check != -1");
                debug("decryption failed, but the program could be configured to work anyway, sometimes the decrypted data comes out fine but it throws errors anyway, probably because something is coming up as insecure");
                return -1;
            }
        }
 
        std::string keyToString()
        {
            return (const char*)key;
        }
 
        std::string ivToString()
        {
            return (const char*)iv;
        }
 
        void keyFromString(std::string key)
        {
            strcpy((char*)this->key, key.c_str());
        }
 
        void ivFromString(std::string iv)
        {
            strcpy((char*)this->iv, iv.c_str());
        }
    };
 
    std::ostream& operator<<(std::ostream &os, const  cryptinfo  &e)
    {
        debug("writing cryptinfo key and iv to stream");
        debug("writing key");
        for (int i = 0; i < 32; i++)
        {
            os << e.key[i];
        }
        os << e.key[32];
        debug("key written");
        debug("writing iv");
        for (int i = 0; i < AES_BLOCK_SIZE; i++)
        {
            os << e.iv[i];
        }
        os << e.iv[16];
        debug("iv written");
        debug("writing cryptinfo to stream good");
        return os;
    }
 
    char* operator<<(char* os, cryptinfo  &e)
    {
        debug("writing cryptinfo key and iv to buffer");
        debug("writing key");
        for (int i = 0; i < 33; i++)
        {
            os[i] = e.key[i];
        }
        debug("key written");
        debug("writing iv");
        for (int i = 33, j = 0; i < 33 + AES_BLOCK_SIZE + 1; ++i, ++j)
        {
            os[i] = e.iv[j];
        }
        debug("iv written");
        debug("writing cryptinfo to buffer good");
        return os;
    }
 
    std::istream& operator>>(std::istream &os, cryptinfo  &e)
    {
        debug("reading key and iv from stream into cryptinfo");
        debug("reading key");
        for (int i = 0; i < 33; i++)
        {
            os >> e.key[i];
        }
        debug("key read");
        debug("reading iv");
        for (int i = 0; i < AES_BLOCK_SIZE + 1; i++)
        {
            os >> e.iv[i];
        }
        debug("iv read");
        debug("reading key and iv from stream good");
        return os;
    }
 
    char* operator>>(char* os, cryptinfo  &e)
    {
        debug("reading key and iv from buffer into cryptinfo");
        debug("reading key");
        for (int i = 0; i < 33; i++)
        {
            e.key[i] = os[i];
        }
        debug("key read");
        debug("reading iv");
        for (int i = 33; i < 33 + AES_BLOCK_SIZE + 1; i++)
        {
            e.iv[i] = os[i];
        }
        debug("iv read");
        debug("reading key and iv from buffer good");
        return os;
    }
};
 

Code: Select all

#pragma once
#include <string>
#include <iostream>
 
//if debug isn't defined, turns into a no-op
template <typename ...T>
void debug(std::string file, int line, T&& ...args)
{
    #ifdef _DEBUG
        unsigned int index = file.find_last_of('\\');
        file[index] = '/';
        index = file.find_last_of('\\', --index);
        std::string finalfile = file.substr(index);
        finalfile[0] = '/';
        std::cout << finalfile << ":" << line << " ";
        using expander = int[];
        (void)expander {
            0, (void(std::cout << std::forward<T>(args)), 0)...
        };
        std::cout << std::endl;
    #endif
}
 
//use this, it outputs the file and line the output was made from!
#define debug(...) debug(__FILE__, __LINE__, __VA_ARGS__)
 
Do you need to free the ctx after you use it or can you use it multiple times? Other than that issue this class should get you encrypting and decrypting bytes real quick. Building OpenSSL is the real trick I guess. Then you just need to find a legit example which I did lol.
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by devsh »

IrrlichtBAW uses OpenSSL for encrypton and decryption of its own BAW model format, you might want to look at how that works there
Dreadstew
Posts: 23
Joined: Wed Apr 01, 2015 5:18 pm

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by Dreadstew »

Code: Select all

 
#pragma once
#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>
 
namespace ga {
    class sleeper {
        std::timed_mutex mut_;
        std::atomic_bool locked_;
    
        void lock()
        {
            mut_.lock();
            locked_ = true;
        }
    
        void unlock()
        {
            locked_ = false;
            mut_.unlock();
        }
 
    public:
 
        sleeper()
        {
            lock();
        }
    
        ~sleeper() {
            if (locked_)
            {
                unlock();
            }
        }
    
        template<typename Rep, typename Period >
        void sleepFor(const std::chrono::duration<Rep, Period>& timeout_duration)
        {
            if (mut_.try_lock_for(timeout_duration))
            {
                mut_.unlock();
            }
        }
    
        void wake() {
            if (locked_)
            {
                unlock();
            }
        }
    };
};
 
sleeper! Gives you the ability to "wake" a thread you are calling sleep in. Good for handling timeouts with threads. I was having issues... I create threads in my event receiver and sleep in them for 3 seconds, then reset my login status message. This worked for fine for error messages but when you succesfully login I needed to clean up the stack the threads were part of, so I had to join them. Joining a sleeping thread will have you sitting waiting out its sleep timer. So you have a handle to your sleep object in your main thread and inside the thread, call sleepFor in the thread, and when you would join the thread in the main thread just call wake on your sleep object and you won't have to wait the sleep.
Dreadstew
Posts: 23
Joined: Wed Apr 01, 2015 5:18 pm

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by Dreadstew »

devsh wrote:IrrlichtBAW uses OpenSSL for encrypton and decryption of its own BAW model format, you might want to look at how that works there
Why would you encrypt a model lol? Can I make a packet out of that format? If so that sounds dank.
denzelbro
Posts: 50
Joined: Wed Jun 27, 2018 11:53 pm

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by denzelbro »

nice, thanks for sharing Dreadstew. any demo example to test this out?
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by devsh »

I encrypt because when you buy assets you are contractually obligated to keep them secure, unless you buy all rights to that asset... and thats when they become 20x more expensive.
Dreadstew
Posts: 23
Joined: Wed Apr 01, 2015 5:18 pm

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by Dreadstew »

denzel you'll have to come up with a usage for it yourself, I can barely type anymore because my hand decided to go numb lol.

devsh - I see, I know nothing of the graphics side of things. That's good to know. I'm going to work on learning about graphics and stuff while my hand comes back to life lol.
denzelbro
Posts: 50
Joined: Wed Jun 27, 2018 11:53 pm

Re: Encryption and Decryption with OpenSSL - cryptinfo class

Post by denzelbro »

Dreadstew wrote:denzel you'll have to come up with a usage for it yourself, I can barely type anymore because my hand decided to go numb lol.
Ok I see thx. checking at the posted code, it seems it does not handle or anything to do with connection or http request?

EDIT:
so this is only for udp? ok..
Post Reply