added rsa-gen mode

This commit is contained in:
Timerix 2025-09-29 12:22:29 +05:00
parent f933d30863
commit b1ca05759e
6 changed files with 90 additions and 49 deletions

View File

@ -6,17 +6,12 @@ void ClientCredential_free(ClientCredential* cred){
return; return;
free(cred->username.data); free(cred->username.data);
free(cred->aes_key.data); free(cred->aes_key.data);
free(cred->token.data);
RSA_destroyPrivateKey(&cred->sk);
RSA_destroyPublicKey(&cred->pk);
free(cred); free(cred);
} }
#define __passhash_lvl_iter 1e5
#define __rsa_key_size 2048
Result(ClientCredential*) ClientCredential_create(str username, str password){ Result(ClientCredential*) ClientCredential_create(str username, str password){
Deferral(32); Deferral(8);
ClientCredential* cred = (ClientCredential*)malloc(sizeof(ClientCredential)); ClientCredential* cred = (ClientCredential*)malloc(sizeof(ClientCredential));
memset(cred, 0, sizeof(ClientCredential)); memset(cred, 0, sizeof(ClientCredential));
bool success = false; bool success = false;
@ -37,37 +32,15 @@ Result(ClientCredential*) ClientCredential_create(str username, str password){
StringBuilder_append_str(&sb, password); StringBuilder_append_str(&sb, password);
StringBuilder_append_str(&sb, username); StringBuilder_append_str(&sb, username);
Array(u8) password_and_username = str_castTo_Array(StringBuilder_getStr(&sb)); Array(u8) password_and_username = str_castTo_Array(StringBuilder_getStr(&sb));
// lvl 1 hash - is used to generate RSA keys
Array(u8) passhash_lvl1 = Array_alloc(u8, password_hash_size);
cred->aes_key = Array_alloc(u8, password_hash_size); cred->aes_key = Array_alloc(u8, password_hash_size);
cred->token = Array_alloc(u8, password_hash_size);
Defer( Defer(
free(passhash_lvl1.data);
if(!success){ if(!success){
free(cred->aes_key.data); free(cred->aes_key.data);
free(cred->token.data);
} }
); );
hash_password(password_and_username, passhash_lvl1.data, __passhash_lvl_iter); // lvl 1 hash - is used as AES key for user data
// lvl 2 hash - is used as AES key hash_password(password_and_username, cred->aes_key.data, __passhash_lvl_iter);
hash_password(passhash_lvl1, cred->aes_key.data, __passhash_lvl_iter);
// lvl 3 hash - is used to authorize client on server
hash_password(cred->aes_key, cred->token.data, __passhash_lvl_iter);
// generate client rsa keys from password hash
br_hmac_drbg_context passhash_based_rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&passhash_based_rng, &br_sha256_vtable, passhash_lvl1.data, password_hash_size);
// TODO: does client really need it's own RSA private key? At least i should generate it once using seedFromTime and save in a file encrypted by user_data_aes_enc
try_void(RSA_generateKeyPair(__rsa_key_size, &cred->sk, &cred->pk, &passhash_based_rng.vtable));
Defer(
if(!success){
RSA_destroyPrivateKey(&cred->sk);
RSA_destroyPublicKey(&cred->pk);
}
);
DecryptorRSA_construct(&cred->rsa_dec, &cred->sk);
EncryptorRSA_construct(&cred->rsa_enc, &cred->pk);
DecryptorAES_construct(&cred->user_data_aes_dec, cred->aes_key); DecryptorAES_construct(&cred->user_data_aes_dec, cred->aes_key);
EncryptorAES_construct(&cred->user_data_aes_enc, cred->aes_key); EncryptorAES_construct(&cred->user_data_aes_enc, cred->aes_key);

View File

@ -13,7 +13,7 @@ void ServerConnection_close(ServerConnection* conn){
/// @param server_link_cstr address:port:public_key /// @param server_link_cstr address:port:public_key
/// @return /// @return
Result(void) ServerLink_parse(cstr server_link_cstr, EndpointIPv4* server_end_out, br_rsa_public_key* server_key_out){ Result(void) ServerLink_parse(cstr server_link_cstr, EndpointIPv4* server_end_out, br_rsa_public_key* server_key_out){
Deferral(16); Deferral(8);
str server_link_str = str_from_cstr(server_link_cstr); str server_link_str = str_from_cstr(server_link_cstr);
i32 sep_pos = 0; i32 sep_pos = 0;

View File

@ -7,11 +7,6 @@ Result(void) client_run();
typedef struct ClientCredential { typedef struct ClientCredential {
str username; str username;
Array(u8) aes_key; Array(u8) aes_key;
Array(u8) token;
br_rsa_private_key sk;
br_rsa_public_key pk;
EncryptorRSA rsa_enc;
DecryptorRSA rsa_dec;
EncryptorAES user_data_aes_enc; EncryptorAES user_data_aes_enc;
DecryptorAES user_data_aes_dec; DecryptorAES user_data_aes_dec;
} ClientCredential; } ClientCredential;

View File

@ -11,20 +11,16 @@ Result(void) RSA_generateKeyPair(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, br_rsa_private_key* sk, br_rsa_public_key* pk,
const br_prng_class** rng_vtable_ptr) const br_prng_class** rng_vtable_ptr)
{ {
Deferral(16); Deferral(8);
bool success = false; bool success = false;
rng_init_sha256_seedFromTime(rng_vtable_ptr);
void* sk_buf = malloc(BR_RSA_KBUF_PRIV_SIZE(key_size)); void* sk_buf = malloc(BR_RSA_KBUF_PRIV_SIZE(key_size));
Defer(
if(!success)
free(sk_buf)
);
void* pk_buf = malloc(BR_RSA_KBUF_PUB_SIZE(key_size)); void* pk_buf = malloc(BR_RSA_KBUF_PUB_SIZE(key_size));
Defer( Defer(
if(!success) if(!success){
free(pk_buf) free(sk_buf);
free(pk_buf);
}
); );
success = br_rsa_i31_keygen(rng_vtable_ptr, sk, sk_buf, pk, pk_buf, key_size, DEFAULT_PUBLIC_EXPONENT); success = br_rsa_i31_keygen(rng_vtable_ptr, sk, sk_buf, pk, pk_buf, key_size, DEFAULT_PUBLIC_EXPONENT);
@ -35,8 +31,28 @@ Result(void) RSA_generateKeyPair(u32 key_size,
Return RESULT_VOID; Return RESULT_VOID;
} }
Result(void) RSA_generateKeyPairFromTime(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk)
{
Deferral(8);
br_hmac_drbg_context time_based_rng = { .vtable = &br_hmac_drbg_vtable };
rng_init_sha256_seedFromTime(&time_based_rng.vtable);
try_void(RSA_generateKeyPair(key_size, sk, pk, &time_based_rng.vtable));
Return RESULT_VOID;
}
Result(void) RSA_generateKeyPairFromPassword(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, str password)
{
Deferral(8);
br_hmac_drbg_context password_based_rng = { .vtable = &br_hmac_drbg_vtable };
br_hmac_drbg_init(&password_based_rng, &br_sha256_vtable, password.data, password.size);
try_void(RSA_generateKeyPair(key_size, sk, pk, &password_based_rng.vtable));
Return RESULT_VOID;
}
Result(void) RSA_computePublicKey(const br_rsa_private_key* sk, br_rsa_public_key* pk){ Result(void) RSA_computePublicKey(const br_rsa_private_key* sk, br_rsa_public_key* pk){
Deferral(16); Deferral(8);
br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus; br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus;
br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp; br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp;

View File

@ -18,6 +18,7 @@
void hash_password(Array(u8) password, u8* out_buffer, i32 iterations); void hash_password(Array(u8) password, u8* out_buffer, i32 iterations);
#define password_hash_size 32 #define password_hash_size 32
#define __passhash_lvl_iter 1e5
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// rng.c // // rng.c //
@ -86,6 +87,8 @@ void DecryptorAES_decrypt(DecryptorAES* ptr, Array(u8) src, Array(u8) dst, u32*
// RSA.c // // RSA.c //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#define __rsa_key_size_default 3072
/// @brief generate random key pair based on system time /// @brief generate random key pair based on system time
/// @param key_size size of public key in bits (2048/3072/4096) /// @param key_size size of public key in bits (2048/3072/4096)
/// @param sk key for decryption /// @param sk key for decryption
@ -95,6 +98,12 @@ Result(void) RSA_generateKeyPair(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, br_rsa_private_key* sk, br_rsa_public_key* pk,
const br_prng_class** rng_vtable_ptr); const br_prng_class** rng_vtable_ptr);
Result(void) RSA_generateKeyPairFromTime(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk);
Result(void) RSA_generateKeyPairFromPassword(u32 key_size,
br_rsa_private_key* sk, br_rsa_public_key* pk, str password);
static inline void RSA_destroyPrivateKey(br_rsa_private_key* sk){ static inline void RSA_destroyPrivateKey(br_rsa_private_key* sk){
free(sk->p); free(sk->p);
} }

View File

@ -5,6 +5,7 @@
typedef enum ProgramMode { typedef enum ProgramMode {
Client, Client,
Server, Server,
RsaGen,
} ProgramMode; } ProgramMode;
#define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL)) #define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL))
@ -14,6 +15,7 @@ int main(const int argc, cstr const* argv){
ProgramMode mode = Client; ProgramMode mode = Client;
cstr server_endpoint_cstr; cstr server_endpoint_cstr;
u32 key_size = 0;
for(int argi = 1; argi < argc; argi++){ for(int argi = 1; argi < argc; argi++){
str arg_str = str_from_cstr(argv[argi]); str arg_str = str_from_cstr(argv[argi]);
@ -23,6 +25,7 @@ int main(const int argc, cstr const* argv){
"no arguments Interactive client mode.\n" "no arguments Interactive client mode.\n"
"-h, --help Show this message.\n" "-h, --help Show this message.\n"
"-l, --listen [addr:port] Start server.\n" "-l, --listen [addr:port] Start server.\n"
"--rsa-gen [size(2048/3072/4096)] Generate RSA private and public keys based on stdin data (64Kb max)\n"
); );
Return 0; Return 0;
} }
@ -39,6 +42,21 @@ int main(const int argc, cstr const* argv){
} }
server_endpoint_cstr = argv[argi]; server_endpoint_cstr = argv[argi];
} }
else if(arg_is("--rsa-gen")){
if(mode != Client){
printf("program mode is set already\n");
Return 1;
}
mode = RsaGen;
if(++argi >= argc){
printfe("ERROR: no key size specified\n");
Return 1;
}
if(sscanf(argv[argi], "%u", &key_size) != 1){
printfe("ERROR: no key size specified\n");
}
}
else { else {
printfe("ERROR: unknown argument '%s'\n" printfe("ERROR: unknown argument '%s'\n"
"Use '-h' to see list of avaliable arguments\n", "Use '-h' to see list of avaliable arguments\n",
@ -57,6 +75,36 @@ int main(const int argc, cstr const* argv){
case Server: case Server:
try_fatal_void(server_run(server_endpoint_cstr)); try_fatal_void(server_run(server_endpoint_cstr));
break; break;
case RsaGen:{
size_t input_max_size = 64*1024;
char* input_buf = malloc(input_max_size);
Defer(free(input_buf));
size_t read_n = fread(input_buf, 1, input_max_size, stdin);
if(read_n == 0){
printfe("ERROR: no input\n");
Return 1;
}
str input_str = str_construct(input_buf, read_n, false);
printfe("generating RSA key pair...\n");
br_rsa_private_key sk;
br_rsa_public_key pk;
try_fatal_void(RSA_generateKeyPairFromPassword(key_size, &sk, &pk, input_str));
Defer(
RSA_destroyPrivateKey(&sk);
RSA_destroyPublicKey(&pk);
);
puts("-----BEGIN RSA PRIVATE KEY-----");
str sk_str = RSA_serializePrivateKey_base64(&sk);
puts(sk_str.data);
free(sk_str.data);
puts("-----END RSA PRIVATE KEY-------");
puts("-----BEGIN RSA PUBLIC KEY------");
str pk_str = RSA_serializePublicKey_base64(&pk);
puts(pk_str.data);
free(pk_str.data);
puts("-----END RSA PUBLIC KEY--------");
}
break;
default: default:
printfe("ERROR: invalid program mode %i\n", mode); printfe("ERROR: invalid program mode %i\n", mode);
Return 1; Return 1;