Compare commits
2 Commits
a44810a181
...
2fb4657fed
| Author | SHA1 | Date | |
|---|---|---|---|
| 2fb4657fed | |||
| ad3afdfc39 |
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 921bada09a86f2364464f8ce9301048e5a8e5344
|
Subproject commit ebe6e58ef3b777a7e45f10b5552ca95bc96e8cc8
|
||||||
@ -137,8 +137,9 @@ case "$TASK" in
|
|||||||
# requires graphviz (https://www.graphviz.org/download/source/)
|
# requires graphviz (https://www.graphviz.org/download/source/)
|
||||||
gprof)
|
gprof)
|
||||||
OUTDIR="$OUTDIR/gprof"
|
OUTDIR="$OUTDIR/gprof"
|
||||||
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
# arguments that emit some call counter code and disable optimizations to see function names
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg"
|
# https://github.com/msys2/MINGW-packages/issues/8503#issuecomment-1365475205
|
||||||
|
C_ARGS="-O0 -g -pg -no-pie -fno-omit-frame-pointer -fno-inline-functions -fno-inline-functions-called-once -fno-optimize-sibling-calls -fopenmp"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
|
|||||||
139
src/cryptography.c
Executable file
139
src/cryptography.c
Executable file
@ -0,0 +1,139 @@
|
|||||||
|
#include "cryptography.h"
|
||||||
|
#include <BearSSL/inc/bearssl_block.h>
|
||||||
|
#include <BearSSL/inc/bearssl_hash.h>
|
||||||
|
#include <BearSSL/inc/bearssl_rand.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
51
src/cryptography.h
Executable file
51
src/cryptography.h
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <tlibc/include/std.h>
|
||||||
|
#include <tlibc/include/collections/Array.h>
|
||||||
|
#include <tlibc/include/string/str.h>
|
||||||
|
|
||||||
|
/// @brief hashes password multiple times using its own hash as salt
|
||||||
|
/// @param password some byte array
|
||||||
|
/// @param iterations number of iterations
|
||||||
|
/// @return Array<u8, 32>
|
||||||
|
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<u8, 16 | 24 | 32>
|
||||||
|
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<u8, 16 | 24 | 32>
|
||||||
|
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;
|
||||||
84
src/main.c
84
src/main.c
@ -1,66 +1,40 @@
|
|||||||
#include <tlibc/include/std.h>
|
#include <cryptography.h>
|
||||||
#include <BearSSL/inc/bearssl_block.h>
|
#include <tlibc/include/string/StringBuilder.h>
|
||||||
#include <BearSSL/inc/bearssl_hash.h>
|
|
||||||
#include <BearSSL/inc/bearssl_rand.h>
|
|
||||||
|
|
||||||
char *print_hex_memory(u8 *p, u32 len) {
|
str hex_to_str(Array buf) {
|
||||||
char tmp[3];
|
StringBuilder sb = StringBuilder_alloc(buf.size * 2 + 1);
|
||||||
u32 output_len = len*2+1;
|
StringBuilder_append_memory(&sb, buf);
|
||||||
char *output = (char*)malloc(output_len);
|
return StringBuilder_getStr(&sb);
|
||||||
memset(output, 0, output_len);
|
|
||||||
for (u32 i=0; i < len; i++) {
|
|
||||||
sprintf(tmp, "%02x", p[i]);
|
|
||||||
strcat(output, tmp);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
const char key_raw[] = "abobus";
|
const str password = STR("abobus");
|
||||||
const u32 key_raw_len = ARRAY_SIZE(key_raw)-1;
|
const Array data = str_castTo_Array(STR("0123456789_hii_"));
|
||||||
const char data[] = "0123456789_hii_"; // must be multiple of 16
|
|
||||||
const u32 data_len = ARRAY_SIZE(data);
|
|
||||||
|
|
||||||
u8 hash_buffer[br_sha256_SIZE];
|
const Array key_hash = hash_password(password, 1e5);
|
||||||
const u32 hash_buffer_len = ARRAY_SIZE(hash_buffer);
|
str hash_str = hex_to_str(key_hash);
|
||||||
memset(hash_buffer, 0, hash_buffer_len);
|
printf("password hash [%i] %s\n", key_hash.size, hash_str.data);
|
||||||
memcpy(hash_buffer, key_raw, key_raw_len);
|
free(hash_str.data);
|
||||||
|
|
||||||
br_sha256_context sha256_ctx;
|
// SHA256 accepts keys with size 16, 24 or 32
|
||||||
br_sha256_init(&sha256_ctx);
|
const u32 key_size = 32;
|
||||||
|
const Array key = Array_construct_size(key_hash.data, key_size);
|
||||||
|
|
||||||
// hash multiple times
|
EncryptorAES* encr = EncryptorAES_create(key);
|
||||||
for(i32 i = 0; i < 8; i++){
|
Array buffer = Array_alloc_size(EncryptorAES_calcDstSize(data.size));
|
||||||
br_sha256_update(&sha256_ctx, hash_buffer, hash_buffer_len);
|
EncryptorAES_encrypt(encr, data, buffer);
|
||||||
br_sha256_out(&sha256_ctx, hash_buffer);
|
EncryptorAES_destroy(encr);
|
||||||
printf("hash(i=%i) %s\n", i, print_hex_memory(hash_buffer, hash_buffer_len));
|
str encrypted_str = hex_to_str(buffer);
|
||||||
}
|
printf("data encrypted (hex): %s\n", encrypted_str.data);
|
||||||
|
free(encrypted_str.data);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
printf("data decrypted\n");
|
|
||||||
fwrite(buffer, 1, buffer_len, stdout);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user