diff --git a/src/client/ClientCredential.c b/src/client/ClientCredential.c index 01e57fc..dcdcf71 100644 --- a/src/client/ClientCredential.c +++ b/src/client/ClientCredential.c @@ -6,17 +6,12 @@ void ClientCredential_free(ClientCredential* cred){ return; free(cred->username.data); free(cred->aes_key.data); - free(cred->token.data); - RSA_destroyPrivateKey(&cred->sk); - RSA_destroyPublicKey(&cred->pk); free(cred); } -#define __passhash_lvl_iter 1e5 -#define __rsa_key_size 2048 Result(ClientCredential*) ClientCredential_create(str username, str password){ - Deferral(32); + Deferral(8); ClientCredential* cred = (ClientCredential*)malloc(sizeof(ClientCredential)); memset(cred, 0, sizeof(ClientCredential)); bool success = false; @@ -37,37 +32,15 @@ Result(ClientCredential*) ClientCredential_create(str username, str password){ StringBuilder_append_str(&sb, password); StringBuilder_append_str(&sb, username); 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->token = Array_alloc(u8, password_hash_size); Defer( - free(passhash_lvl1.data); if(!success){ free(cred->aes_key.data); - free(cred->token.data); - } - ); - hash_password(password_and_username, passhash_lvl1.data, __passhash_lvl_iter); - // lvl 2 hash - is used as AES key - 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); } ); + // lvl 1 hash - is used as AES key for user data + hash_password(password_and_username, cred->aes_key.data, __passhash_lvl_iter); - DecryptorRSA_construct(&cred->rsa_dec, &cred->sk); - EncryptorRSA_construct(&cred->rsa_enc, &cred->pk); DecryptorAES_construct(&cred->user_data_aes_dec, cred->aes_key); EncryptorAES_construct(&cred->user_data_aes_enc, cred->aes_key); diff --git a/src/client/ServerConnection.c b/src/client/ServerConnection.c index db25934..16cc892 100644 --- a/src/client/ServerConnection.c +++ b/src/client/ServerConnection.c @@ -13,7 +13,7 @@ void ServerConnection_close(ServerConnection* conn){ /// @param server_link_cstr address:port:public_key /// @return 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); i32 sep_pos = 0; diff --git a/src/client/client.h b/src/client/client.h index 78c0bd8..d0a9c8f 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -7,11 +7,6 @@ Result(void) client_run(); typedef struct ClientCredential { str username; 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; DecryptorAES user_data_aes_dec; } ClientCredential; diff --git a/src/cryptography/RSA.c b/src/cryptography/RSA.c index e90abc8..739e437 100644 --- a/src/cryptography/RSA.c +++ b/src/cryptography/RSA.c @@ -11,20 +11,16 @@ Result(void) RSA_generateKeyPair(u32 key_size, br_rsa_private_key* sk, br_rsa_public_key* pk, const br_prng_class** rng_vtable_ptr) { - Deferral(16); + Deferral(8); bool success = false; - rng_init_sha256_seedFromTime(rng_vtable_ptr); 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)); Defer( - if(!success) - free(pk_buf) + if(!success){ + 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); @@ -35,8 +31,28 @@ Result(void) RSA_generateKeyPair(u32 key_size, 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){ - Deferral(16); + Deferral(8); br_rsa_compute_modulus compute_modulus = br_rsa_i31_compute_modulus; br_rsa_compute_pubexp compute_pubexp = br_rsa_i31_compute_pubexp; diff --git a/src/cryptography/cryptography.h b/src/cryptography/cryptography.h index f478b57..2fbc5df 100755 --- a/src/cryptography/cryptography.h +++ b/src/cryptography/cryptography.h @@ -18,6 +18,7 @@ void hash_password(Array(u8) password, u8* out_buffer, i32 iterations); #define password_hash_size 32 +#define __passhash_lvl_iter 1e5 ////////////////////////////////////////////////////////////////////////////// // rng.c // @@ -86,6 +87,8 @@ void DecryptorAES_decrypt(DecryptorAES* ptr, Array(u8) src, Array(u8) dst, u32* // RSA.c // ////////////////////////////////////////////////////////////////////////////// +#define __rsa_key_size_default 3072 + /// @brief generate random key pair based on system time /// @param key_size size of public key in bits (2048/3072/4096) /// @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, 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){ free(sk->p); } diff --git a/src/main.c b/src/main.c index 7642b9d..db23bbf 100755 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ typedef enum ProgramMode { Client, Server, + RsaGen, } ProgramMode; #define arg_is(LITERAL) str_equals(arg_str, STR(LITERAL)) @@ -14,15 +15,17 @@ int main(const int argc, cstr const* argv){ ProgramMode mode = Client; cstr server_endpoint_cstr; + u32 key_size = 0; for(int argi = 1; argi < argc; argi++){ str arg_str = str_from_cstr(argv[argi]); if(arg_is("-h") || arg_is("--help")){ printf( "USAGE:\n" - "no arguments Interactive client mode.\n" - "-h, --help Show this message.\n" - "-l, --listen [addr:port] Start server.\n" + "no arguments Interactive client mode.\n" + "-h, --help Show this message.\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; } @@ -39,6 +42,21 @@ int main(const int argc, cstr const* argv){ } 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 { printfe("ERROR: unknown argument '%s'\n" "Use '-h' to see list of avaliable arguments\n", @@ -57,6 +75,36 @@ int main(const int argc, cstr const* argv){ case Server: try_fatal_void(server_run(server_endpoint_cstr)); 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: printfe("ERROR: invalid program mode %i\n", mode); Return 1;