From 2fb4657fed33c1f9660cd00314c5167a502ab9e5 Mon Sep 17 00:00:00 2001 From: Timerix Date: Sat, 19 Jul 2025 04:42:53 +0300 Subject: [PATCH] implemented AES encryption and decryption --- dependencies/tlibc | 2 +- src/cryptography.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ src/cryptography.h | 51 +++++++++++++++++ src/main.c | 84 ++++++++++----------------- 4 files changed, 220 insertions(+), 56 deletions(-) create mode 100755 src/cryptography.c create mode 100755 src/cryptography.h diff --git a/dependencies/tlibc b/dependencies/tlibc index 921bada..ebe6e58 160000 --- a/dependencies/tlibc +++ b/dependencies/tlibc @@ -1 +1 @@ -Subproject commit 921bada09a86f2364464f8ce9301048e5a8e5344 +Subproject commit ebe6e58ef3b777a7e45f10b5552ca95bc96e8cc8 diff --git a/src/cryptography.c b/src/cryptography.c new file mode 100755 index 0000000..1e6e858 --- /dev/null +++ b/src/cryptography.c @@ -0,0 +1,139 @@ +#include "cryptography.h" +#include +#include +#include +#include + +Array hash_password(str password, i32 iterations){ + Array hash_buffer = Array_alloc(u8, br_sha256_SIZE); + Array_memset(&hash_buffer, 0); + br_sha256_context sha256_ctx; + br_sha256_init(&sha256_ctx); + + for(i32 i = 0; i < iterations; i++){ + br_sha256_update(&sha256_ctx, password.data, password.size); + br_sha256_out(&sha256_ctx, hash_buffer.data); + br_sha256_update(&sha256_ctx, hash_buffer.data, hash_buffer.size); + } + br_sha256_out(&sha256_ctx, hash_buffer.data); + + return hash_buffer; +} + + +// size must be multiple of 16 +#define __AES_BUFFER_SIZE 256 + +typedef struct EncryptorAES { + br_aes_ct64_cbcenc_keys enc_ctx; + Array buf; + Array iv; +} EncryptorAES; + +typedef struct DecryptorAES { + br_aes_ct64_cbcdec_keys dec_ctx; + Array buf; + Array iv; +} DecryptorAES; + +EncryptorAES* EncryptorAES_create(Array key){ + assert(key.size == 16 || key.size == 24 || key.size == 32); + + EncryptorAES* ptr = (EncryptorAES*)malloc(sizeof(EncryptorAES)); + br_aes_ct64_cbcenc_init(&ptr->enc_ctx, key.data, key.size); + + // size must be multiple of 16 + ptr->buf = Array_alloc(u8, __AES_BUFFER_SIZE); + Array_memset(&ptr->buf, 0); + + // size of one SHA block (16 bytes) + ptr->iv = Array_alloc(u8, 16); + Array_memset(&ptr->iv, 0); + + return ptr; +} + +void EncryptorAES_destroy(EncryptorAES* ptr){ + free(ptr->buf.data); + free(ptr->iv.data); +} + +void EncryptorAES_encrypt(EncryptorAES* ptr, Array src, Array dst){ + assert(dst.size >= EncryptorAES_calcDstSize(src.size)); + + // emit EncryptedBlockInfo to beginning of result + EncryptedBlockInfo block_info = { .padding_size = 16 - src.size % 16 }; + memcpy(dst.data, &block_info, sizeof(block_info)); + dst.data += sizeof(block_info); + dst.size -= sizeof(block_info); + + // write full blocks + while(src.size > ptr->buf.size){ + memcpy(ptr->buf.data, src.data, ptr->buf.size); + src.data += ptr->buf.size; + src.size -= ptr->buf.size; + br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, ptr->buf.size); + memcpy(dst.data, ptr->buf.data, ptr->buf.size); + dst.data += ptr->buf.size; + dst.size -= ptr->buf.size; + } + + // write incomplete block + Array_memset(&ptr->buf, 0); + memcpy(ptr->buf.data, src.data, src.size); + u32 src_size_padded = src.size + block_info.padding_size; + br_aes_ct64_cbcenc_run(&ptr->enc_ctx, ptr->iv.data, ptr->buf.data, src_size_padded); + memcpy(dst.data, ptr->buf.data, src_size_padded); +} + + +DecryptorAES* DecryptorAES_create(Array key){ + assert(key.size == 16 || key.size == 24 || key.size == 32); + + DecryptorAES* ptr = (DecryptorAES*)malloc(sizeof(DecryptorAES)); + br_aes_ct64_cbcdec_init(&ptr->dec_ctx, key.data, key.size); + + // size must be multiple of 16 + ptr->buf = Array_alloc(u8, __AES_BUFFER_SIZE); + Array_memset(&ptr->buf, 0); + + // size of one SHA block (16 bytes) + ptr->iv = Array_alloc(u8, 16); + Array_memset(&ptr->iv, 0); + + return ptr; +} + +void DecryptorAES_destroy(DecryptorAES* ptr){ + free(ptr->buf.data); + free(ptr->iv.data); +} + +void DecryptorAES_decrypt(DecryptorAES* ptr, Array src, Array dst, u32* decrypted_size){ + assert(dst.size >= src.size); + + // read EncryptedBlockInfo from beginning of data + EncryptedBlockInfo block_info; + memcpy(&block_info, src.data, sizeof(block_info)); + src.data += sizeof(block_info); + src.size -= sizeof(block_info); + *decrypted_size = src.size - block_info.padding_size; + + // write full blocks + while(src.size > ptr->buf.size){ + memcpy(ptr->buf.data, src.data, ptr->buf.size); + src.data += ptr->buf.size; + src.size -= ptr->buf.size; + br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, ptr->buf.data, ptr->buf.size); + memcpy(dst.data, ptr->buf.data, ptr->buf.size); + dst.data += ptr->buf.size; + dst.size -= ptr->buf.size; + } + + // write incomplete block + Array_memset(&ptr->buf, 0); + memcpy(ptr->buf.data, src.data, src.size); + u32 src_size_padded = src.size + block_info.padding_size; + br_aes_ct64_cbcdec_run(&ptr->dec_ctx, ptr->iv.data, ptr->buf.data, src_size_padded); + memcpy(dst.data, ptr->buf.data, src_size_padded); +} diff --git a/src/cryptography.h b/src/cryptography.h new file mode 100755 index 0000000..4e06bbb --- /dev/null +++ b/src/cryptography.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include +#include + +/// @brief hashes password multiple times using its own hash as salt +/// @param password some byte array +/// @param iterations number of iterations +/// @return Array +Array hash_password(str password, i32 iterations); + + +typedef struct EncryptedBlockInfo { + u32 padding_size; + u32 _reserved; + u64 __reserved; +} EncryptedBlockInfo; + +typedef struct EncryptorAES EncryptorAES; + +/// @param key Array +EncryptorAES* EncryptorAES_create(Array key); + +void EncryptorAES_destroy(EncryptorAES* ptr); + +/// @brief Encrypts `src` and writes output to `dst`. +/// @param src array of any size +/// @param dst array of size >= EncryptorAES_calcDstSize(src.size) +void EncryptorAES_encrypt(EncryptorAES* ptr, Array src, Array dst); + +#define EncryptorAES_calcDstSize(SRC_SIZE) (ALIGN_TO(SRC_SIZE, 16) + sizeof(EncryptedBlockInfo)) + +typedef struct DecryptorAES DecryptorAES; + +/// @param key Array +DecryptorAES* DecryptorAES_create(Array key); + +void DecryptorAES_destroy(DecryptorAES* ptr); + +/// @brief Decrypts `src` and writes output to `dst`. +/// @param src array of any size +/// @param dst array of size >= src.size +/// @param decrypted_size size of original data without padding added by EncryptorAES_encrypt +void DecryptorAES_decrypt(DecryptorAES* ptr, Array src, Array dst, u32* decrypted_size); + + + +typedef struct EncryptorRSA EncryptorRSA; + + +typedef struct DecryptorRSA DecryptorRSA; diff --git a/src/main.c b/src/main.c index 4875dfc..ab409ca 100755 --- a/src/main.c +++ b/src/main.c @@ -1,66 +1,40 @@ -#include -#include -#include -#include +#include +#include -char *print_hex_memory(u8 *p, u32 len) { - char tmp[3]; - u32 output_len = len*2+1; - char *output = (char*)malloc(output_len); - memset(output, 0, output_len); - for (u32 i=0; i < len; i++) { - sprintf(tmp, "%02x", p[i]); - strcat(output, tmp); - } - return output; +str hex_to_str(Array buf) { + StringBuilder sb = StringBuilder_alloc(buf.size * 2 + 1); + StringBuilder_append_memory(&sb, buf); + return StringBuilder_getStr(&sb); } int main(){ - const char key_raw[] = "abobus"; - const u32 key_raw_len = ARRAY_SIZE(key_raw)-1; - const char data[] = "0123456789_hii_"; // must be multiple of 16 - const u32 data_len = ARRAY_SIZE(data); - - u8 hash_buffer[br_sha256_SIZE]; - const u32 hash_buffer_len = ARRAY_SIZE(hash_buffer); - memset(hash_buffer, 0, hash_buffer_len); - memcpy(hash_buffer, key_raw, key_raw_len); - - br_sha256_context sha256_ctx; - br_sha256_init(&sha256_ctx); - - // hash multiple times - for(i32 i = 0; i < 8; i++){ - br_sha256_update(&sha256_ctx, hash_buffer, hash_buffer_len); - br_sha256_out(&sha256_ctx, hash_buffer); - printf("hash(i=%i) %s\n", i, print_hex_memory(hash_buffer, hash_buffer_len)); - } + const str password = STR("abobus"); + const Array data = str_castTo_Array(STR("0123456789_hii_")); + const Array key_hash = hash_password(password, 1e5); + str hash_str = hex_to_str(key_hash); + printf("password hash [%i] %s\n", key_hash.size, hash_str.data); + free(hash_str.data); - u8 key_padded[32]; // must be 16 or 24 or 32 - const u32 key_padded_len = ARRAY_SIZE(key_padded); - memset(key_padded, 0, key_padded_len); - memcpy(key_padded, hash_buffer, key_padded_len); + // SHA256 accepts keys with size 16, 24 or 32 + const u32 key_size = 32; + const Array key = Array_construct_size(key_hash.data, key_size); - u8 buffer[512]; - const u32 buffer_len = ARRAY_SIZE(buffer); - memset(buffer, 0, buffer_len); - memcpy(buffer, data, data_len); - - br_aes_ct64_cbcenc_keys enc_ctx; - br_aes_ct64_cbcenc_init(&enc_ctx, key_padded, key_padded_len); - u8 iv[16]; - memset(iv, 0, ARRAY_SIZE(iv)); - br_aes_ct64_cbcenc_run(&enc_ctx, iv, buffer, buffer_len); - - printf("data encrypted\n"); + EncryptorAES* encr = EncryptorAES_create(key); + Array buffer = Array_alloc_size(EncryptorAES_calcDstSize(data.size)); + EncryptorAES_encrypt(encr, data, buffer); + EncryptorAES_destroy(encr); + str encrypted_str = hex_to_str(buffer); + printf("data encrypted (hex): %s\n", encrypted_str.data); + free(encrypted_str.data); - br_aes_ct64_cbcdec_keys dec_ctx; - br_aes_ct64_cbcdec_init(&dec_ctx, key_padded, key_padded_len); - memset(iv, 0, ARRAY_SIZE(iv)); - br_aes_ct64_cbcdec_run(&dec_ctx, iv, buffer, buffer_len); + DecryptorAES* decr = DecryptorAES_create(key); + u32 decrypted_size = 0; + DecryptorAES_decrypt(decr, buffer, buffer, &decrypted_size); + DecryptorAES_destroy(decr); + str decrypted_str = str_copy(str_construct(buffer.data, decrypted_size, false)); + printf("data decrypted (utf8): %s\n", decrypted_str.data); + free(decrypted_str.data); - printf("data decrypted\n"); - fwrite(buffer, 1, buffer_len, stdout); return 0; } \ No newline at end of file