Skip to content

Instantly share code, notes, and snippets.

@maldevel
Created November 8, 2018 18:20
Show Gist options
  • Save maldevel/08d07c24c67bea36f0db2019232ffa38 to your computer and use it in GitHub Desktop.
Save maldevel/08d07c24c67bea36f0db2019232ffa38 to your computer and use it in GitHub Desktop.
Dexter AES 256 CBC mode encryption code snippet
//https://github.com/twelvesec/dexter
//GNU General Public License v3.0
//@maldevel
//...
static bool derive_key_from_password(std::string password, HCRYPTKEY *key, HCRYPTPROV *hCryptProv) {
HCRYPTHASH hHash = 0;
bool success = true;
if (success && CryptAcquireContext(hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT) == FALSE) {
success = false;
}
if (success && CryptCreateHash(*hCryptProv, CALG_SHA_256, 0, 0, &hHash) == FALSE) {
success = false;
}
if (success && CryptHashData(hHash, (BYTE*)password.c_str(), (DWORD)password.length(), 0) == FALSE) {
success = false;
}
if (success && CryptDeriveKey(*hCryptProv, CALG_AES_256, hHash, CRYPT_EXPORTABLE, key) == FALSE) {
success = false;
}
if (hHash) {
CryptDestroyHash(hHash);
hHash = 0;
}
return success;
}
std::string libcrypt::encrypt(std::string password, std::string plaintext) {
std::string ciphertext;
DWORD ciphersize = 0;
DWORD ciphertempsize = 0;
BYTE *cipher = 0;
BYTE *ivandcipher = 0;
DWORD ivandciphersize = 0;
HCRYPTKEY key = 0;
HCRYPTPROV hCryptProv = 0;
DWORD mode = CRYPT_MODE_CBC;
DWORD padding = PKCS5_PADDING;
DWORD blocksize = 0, blocksizelen = sizeof(DWORD);
BYTE *iv = 0;
bool success = true;
if (success && derive_key_from_password(password, &key, &hCryptProv) == false) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_MODE, (BYTE*)&mode, 0) == FALSE) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_PADDING, (BYTE*)&padding, 0) == FALSE) {
success = false;
}
if (success && CryptGetKeyParam(key, KP_BLOCKLEN, (BYTE*)&blocksize, &blocksizelen, 0) == FALSE) {
success = false;
}
blocksize /= 8;
if (success && (iv = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, blocksize * sizeof(BYTE))) == NULL) {
success = false;
}
if (success && CryptGenRandom(hCryptProv, blocksize, iv) == FALSE) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_IV, iv, 0) == FALSE) {
success = false;
}
ciphersize = (DWORD)plaintext.length();
if (success && CryptEncrypt(key, 0, TRUE, 0, NULL, &ciphersize, 0) == FALSE) {
success = false;
}
if (success && (cipher = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ciphersize * sizeof(BYTE))) == NULL) {
success = false;
}
if (success && memcpy_s(cipher, ciphersize, plaintext.c_str(), plaintext.length()) != 0) {
success = false;
}
ciphertempsize = ciphersize;
ciphersize = (DWORD)plaintext.length();
if (success && CryptEncrypt(key, 0, TRUE, 0, cipher, &ciphersize, ciphertempsize) == FALSE) {
success = false;
}
ivandciphersize = ciphersize + blocksize;
if (success && (ivandcipher = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ivandciphersize * sizeof(BYTE))) == NULL) {
success = false;
}
if (success && (memcpy_s(ivandcipher, ivandciphersize, iv, blocksize) != 0 || memcpy_s(ivandcipher + blocksize, ivandciphersize, cipher, ciphersize) != 0)) {
success = false;
}
if (success && (ciphertext = libencode::base64_encode(ivandcipher, ivandciphersize)) == "") {
success = false;
}
if (ivandcipher) {
HeapFree(GetProcessHeap(), 0, ivandcipher);
ivandcipher = NULL;
}
if (cipher) {
HeapFree(GetProcessHeap(), 0, cipher);
cipher = NULL;
}
if (iv) {
HeapFree(GetProcessHeap(), 0, iv);
iv = NULL;
}
if (key) {
CryptDestroyKey(key);
key = NULL;
}
if (hCryptProv) {
CryptReleaseContext(hCryptProv, 0);
hCryptProv = NULL;
}
return ciphertext;
}
std::string libcrypt::decrypt(std::string password, std::string ciphertext) {
std::string plaintext;
bool success = true;
HCRYPTKEY key = 0;
HCRYPTPROV hCryptProv = 0;
DWORD mode = CRYPT_MODE_CBC;
DWORD padding = PKCS5_PADDING;
DWORD blocksize = 0, blocksizelen = sizeof(DWORD);
BYTE *iv = 0;
BYTE *decoded = 0;
BYTE *ivandcipher = 0;
DWORD ivandciphersize = 0;
if (success && derive_key_from_password(password, &key, &hCryptProv) == false) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_MODE, (BYTE*)&mode, 0) == FALSE) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_PADDING, (BYTE*)&padding, 0) == FALSE) {
success = false;
}
if (success && CryptGetKeyParam(key, KP_BLOCKLEN, (BYTE*)&blocksize, &blocksizelen, 0) == FALSE) {
success = false;
}
blocksize /= 8;
if (success && (iv = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, blocksize * sizeof(BYTE))) == NULL) {
success = false;
}
if (success && (ivandciphersize = libencode::base64_decode(&decoded, ciphertext.c_str())) == 0) {
success = false;
}
ivandciphersize -= blocksize;
if (success && (ivandcipher = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ivandciphersize * sizeof(BYTE))) == NULL) {
success = false;
}
if (success && (memcpy_s(iv, blocksize, decoded, blocksize) != 0 || memcpy_s(ivandcipher, ivandciphersize, decoded + blocksize, ivandciphersize) != 0)) {
success = false;
}
if (success && CryptSetKeyParam(key, KP_IV, iv, 0) == FALSE) {
success = false;
}
if (CryptDecrypt(key, 0, TRUE, 0, ivandcipher, &ivandciphersize) == FALSE) {
success = false;
}
ivandcipher[ivandciphersize] = 0;
plaintext = std::string((char*)ivandcipher);
if (iv) {
HeapFree(GetProcessHeap(), 0, iv);
iv = NULL;
}
if (decoded) {
HeapFree(GetProcessHeap(), 0, decoded);
decoded = NULL;
}
if (ivandcipher) {
HeapFree(GetProcessHeap(), 0, ivandcipher);
ivandcipher = NULL;
}
if (key) {
CryptDestroyKey(key);
key = NULL;
}
if (hCryptProv) {
CryptReleaseContext(hCryptProv, 0);
hCryptProv = NULL;
}
return plaintext;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment