Distinguish ED25519 for signing and X25519 for key exchange and encryption

This commit is contained in:
Night Kaly 2024-09-25 09:55:05 +01:00
parent 2680bc40d6
commit 46e8b3c8e8
Signed by: night0721
GPG key ID: 957D67B8DB7A119B
5 changed files with 76 additions and 34 deletions

View file

@ -7,15 +7,17 @@
#define TIME_SIZE sizeof(time_t) #define TIME_SIZE sizeof(time_t)
#define SIGN_SIZE crypto_sign_BYTES #define SIGN_SIZE crypto_sign_BYTES
#define PK_RAW_SIZE crypto_kx_PUBLICKEYBYTES #define PK_ED25519_SIZE crypto_sign_PUBLICKEYBYTES /* 32, size for signature keys */
#define SK_RAW_SIZE crypto_sign_SECRETKEYBYTES #define SK_ED25519_SIZE crypto_sign_SECRETKEYBYTES /* 64 */
#define PK_DATA_SIZE PK_RAW_SIZE + MAX_NAME + TIME_SIZE #define PK_X25519_SIZE crypto_kx_PUBLICKEYBYTES /* 32, size for key exchange keys */
#define SK_X25519_SIZE crypto_kx_PUBLICKEYBYTES /* same with public key */
#define PK_DATA_SIZE PK_ED25519_SIZE + MAX_NAME + TIME_SIZE
#define PK_SIZE PK_DATA_SIZE + SIGN_SIZE /* Size with signature */ #define PK_SIZE PK_DATA_SIZE + SIGN_SIZE /* Size with signature */
#define SK_SIZE SK_RAW_SIZE #define SK_SIZE SK_ED25519_SIZE
#define SHARED_KEY_SIZE crypto_kx_SESSIONKEYBYTES #define SHARED_KEY_SIZE crypto_kx_SESSIONKEYBYTES
typedef struct public_key { typedef struct public_key {
uint8_t raw[PK_RAW_SIZE]; uint8_t raw[PK_ED25519_SIZE];
uint8_t username[MAX_NAME]; uint8_t username[MAX_NAME];
time_t creation; time_t creation;
uint8_t signature[SIGN_SIZE]; uint8_t signature[SIGN_SIZE];

View file

@ -4,7 +4,7 @@
keypair_t *create_keypair(char *username) keypair_t *create_keypair(char *username)
{ {
uint8_t pk_raw[PK_RAW_SIZE], sk[SK_SIZE], pk_data[PK_DATA_SIZE], uint8_t pk_raw[PK_ED25519_SIZE], sk[SK_SIZE], pk_data[PK_DATA_SIZE],
username_padded[MAX_NAME], pk_hash[HASH_SIZE], pk_sign[SIGN_SIZE], username_padded[MAX_NAME], pk_hash[HASH_SIZE], pk_sign[SIGN_SIZE],
pk[PK_SIZE]; pk[PK_SIZE];
@ -22,9 +22,9 @@ keypair_t *create_keypair(char *username)
return NULL; return NULL;
} }
memcpy(pk_data, pk_raw, PK_RAW_SIZE); memcpy(pk_data, pk_raw, PK_ED25519_SIZE);
memcpy(pk_data + PK_RAW_SIZE, username_padded, MAX_NAME); memcpy(pk_data + PK_ED25519_SIZE, username_padded, MAX_NAME);
memcpy(pk_data + PK_RAW_SIZE + MAX_NAME, &current_time, TIME_SIZE); memcpy(pk_data + PK_ED25519_SIZE + MAX_NAME, &current_time, TIME_SIZE);
crypto_generichash(pk_hash, HASH_SIZE, pk_data, PK_DATA_SIZE, NULL, 0); crypto_generichash(pk_hash, HASH_SIZE, pk_data, PK_DATA_SIZE, NULL, 0);
crypto_sign_detached(pk_sign, NULL, pk_hash, HASH_SIZE, sk); crypto_sign_detached(pk_sign, NULL, pk_hash, HASH_SIZE, sk);
@ -53,7 +53,7 @@ keypair_t *create_keypair(char *username)
fclose(keyf); fclose(keyf);
keypair_t *kp = memalloc(sizeof(keypair_t)); keypair_t *kp = memalloc(sizeof(keypair_t));
memcpy(kp->pk.raw, pk_raw, PK_RAW_SIZE); memcpy(kp->pk.raw, pk_raw, PK_ED25519_SIZE);
memcpy(kp->pk.username, username_padded, MAX_NAME); memcpy(kp->pk.username, username_padded, MAX_NAME);
kp->pk.creation = current_time; kp->pk.creation = current_time;
memcpy(kp->pk.signature, pk_sign, SIGN_SIZE); memcpy(kp->pk.signature, pk_sign, SIGN_SIZE);
@ -92,10 +92,10 @@ keypair_t *get_keypair(char *username)
keypair_t *kp = memalloc(sizeof(keypair_t)); keypair_t *kp = memalloc(sizeof(keypair_t));
memcpy(kp->pk.raw, pk, PK_RAW_SIZE); memcpy(kp->pk.raw, pk, PK_ED25519_SIZE);
memcpy(kp->pk.username, pk + PK_RAW_SIZE, MAX_NAME); memcpy(kp->pk.username, pk + PK_ED25519_SIZE, MAX_NAME);
memcpy(&kp->pk.creation, pk + PK_RAW_SIZE + MAX_NAME, TIME_SIZE); memcpy(&kp->pk.creation, pk + PK_ED25519_SIZE + MAX_NAME, TIME_SIZE);
memcpy(kp->pk.signature, pk + PK_RAW_SIZE + MAX_NAME + TIME_SIZE, SIGN_SIZE); memcpy(kp->pk.signature, pk + PK_DATA_SIZE, SIGN_SIZE);
memcpy(kp->pk.full, pk, PK_SIZE); memcpy(kp->pk.full, pk, PK_SIZE);
memcpy(kp->sk, sk, SK_SIZE); memcpy(kp->sk, sk, SK_SIZE);
@ -108,14 +108,14 @@ keypair_t *get_keypair(char *username)
*/ */
uint8_t *get_pk_from_ks(char *username) uint8_t *get_pk_from_ks(char *username)
{ {
size_t bin_len = PK_RAW_SIZE; size_t bin_len = PK_ED25519_SIZE;
unsigned char *bin = memalloc(bin_len); unsigned char *bin = memalloc(bin_len);
/* TEMPORARY */ /* TEMPORARY */
if (strcmp(username, "night") == 0) { if (strcmp(username, "night") == 0) {
sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_RAW_SIZE * 2, NULL, NULL, NULL); sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_ED25519_SIZE * 2, NULL, NULL, NULL);
return bin; return bin;
} else if (strcmp(username, "palanix") == 0) { } else if (strcmp(username, "palanix") == 0) {
sodium_hex2bin(bin, bin_len, "932aee08aa338108e49f65a5c4f0eb0a08a15bf717fdf8c0ff60eefd0ea014ae", PK_RAW_SIZE * 2, NULL, NULL, NULL); sodium_hex2bin(bin, bin_len, "932aee08aa338108e49f65a5c4f0eb0a08a15bf717fdf8c0ff60eefd0ea014ae", PK_ED25519_SIZE * 2, NULL, NULL, NULL);
return bin; return bin;
} }
return NULL; return NULL;

View file

@ -521,15 +521,30 @@ void send_message()
uint8_t *recipient = users->items[current_user].name; uint8_t *recipient = users->items[current_user].name;
keypair_t *kp_from = get_keypair(USERNAME); keypair_t *kp_from = get_keypair(USERNAME);
keypair_t *kp_to = get_keypair(recipient); uint8_t *pk_to = get_pk_from_ks(recipient); /* ed25519 */
int status = ZSM_STA_SUCCESS; int status = ZSM_STA_SUCCESS;
uint8_t *shared_key = get_sharedkey(recipient);
if (shared_key == NULL) {
uint8_t shared_key[SHARED_KEY_SIZE]; uint8_t shared_key[SHARED_KEY_SIZE];
if (crypto_kx_client_session_keys(shared_key, NULL, kp_from->pk.raw,
kp_from->sk, kp_to->pk.raw) != 0) { /* Key exchange need to be done with x25519 public and secret keys */
uint8_t from_pk[PK_X25519_SIZE];
uint8_t to_pk[PK_X25519_SIZE];
uint8_t from_sk[SK_X25519_SIZE];
crypto_sign_ed25519_pk_to_curve25519(from_pk, kp_from->pk.raw);
crypto_sign_ed25519_pk_to_curve25519(to_pk, pk_to);
crypto_sign_ed25519_sk_to_curve25519(from_sk, kp_from->sk);
if (crypto_kx_client_session_keys(shared_key, NULL, from_pk, from_sk,
to_pk) != 0) {
deinit();
/* Recipient public key is suspicious */ /* Recipient public key is suspicious */
write_log(LOG_ERROR, "Error performing key exchange with %s", recipient); error(1, "Error performing key exchange with %s", recipient);
}
save_sharedkey(recipient, shared_key);
} }
size_t content_len = strlen(content); size_t content_len = strlen(content);
@ -548,9 +563,20 @@ void send_message()
size_t data_len = MAX_NAME * 2 + NONCE_SIZE + cipher_len; size_t data_len = MAX_NAME * 2 + NONCE_SIZE + cipher_len;
uint8_t *data = memalloc(data_len); uint8_t *data = memalloc(data_len);
uint8_t recipient_padded[MAX_NAME];
strcpy(recipient_padded, recipient);
size_t length = strlen(recipient);
if (length < MAX_NAME) {
/* Pad with null characters up to max length */
memset(recipient_padded + length, 0, MAX_NAME - length);
} else {
deinit();
error(1, "Recipient username must be shorter than MAX_NAME");
}
/* Construct data */ /* Construct data */
memcpy(data, kp_from->pk.username, MAX_NAME); memcpy(data, kp_from->pk.username, MAX_NAME);
memcpy(data + MAX_NAME, kp_to->pk.username, MAX_NAME); memcpy(data + MAX_NAME, recipient, MAX_NAME);
memcpy(data + MAX_NAME * 2, nonce, NONCE_SIZE); memcpy(data + MAX_NAME * 2, nonce, NONCE_SIZE);
memcpy(data + MAX_NAME * 2 + NONCE_SIZE, encrypted, cipher_len); memcpy(data + MAX_NAME * 2 + NONCE_SIZE, encrypted, cipher_len);
@ -583,6 +609,7 @@ void ui(int *fd)
users = arraylist_init(LINES); users = arraylist_init(LINES);
marked = arraylist_init(100); marked = arraylist_init(100);
sqlite_init(); sqlite_init();
get_users();
draw_users(); draw_users();
refresh(); refresh();
while (1) { while (1) {

View file

@ -89,15 +89,28 @@ void *receive_worker(void *arg)
memcpy(nonce, pkt.data + MAX_NAME * 2, NONCE_SIZE); memcpy(nonce, pkt.data + MAX_NAME * 2, NONCE_SIZE);
memcpy(encrypted, pkt.data + MAX_NAME * 2 + NONCE_SIZE, cipher_len); memcpy(encrypted, pkt.data + MAX_NAME * 2 + NONCE_SIZE, cipher_len);
keypair_t *kp_from = get_keypair(from); uint8_t *pk_from = get_pk_from_ks(from); /* ed25519 */
keypair_t *kp_to = get_keypair(to); keypair_t *kp_to = get_keypair(to);
uint8_t *shared_key = get_sharedkey(from);
if (shared_key == NULL) {
uint8_t shared_key[SHARED_KEY_SIZE]; uint8_t shared_key[SHARED_KEY_SIZE];
if (crypto_kx_client_session_keys(shared_key, NULL, kp_from->pk.raw,
kp_from->sk, kp_to->pk.raw) != 0) { /* Key exchange need to be done with x25519 public and secret keys */
/* Suspicious server public key, bail out */ uint8_t to_pk[PK_X25519_SIZE];
uint8_t from_pk[PK_X25519_SIZE];
uint8_t to_sk[SK_X25519_SIZE];
crypto_sign_ed25519_pk_to_curve25519(to_pk, kp_to->pk.raw);
crypto_sign_ed25519_pk_to_curve25519(from_pk, pk_from);
crypto_sign_ed25519_sk_to_curve25519(to_sk, kp_to->sk);
if (crypto_kx_server_session_keys(shared_key, NULL, to_pk,
to_sk, from_pk) != 0) {
/* Author public key is suspicious */
write_log(LOG_ERROR, "Error performing key exchange with %s", from); write_log(LOG_ERROR, "Error performing key exchange with %s", from);
} }
save_sharedkey(from, shared_key);
}
/* We don't need it anymore */ /* We don't need it anymore */
free(pkt.data); free(pkt.data);

View file

@ -36,9 +36,9 @@ int authenticate_client(int clientfd, uint8_t *username)
goto failure; goto failure;
} }
uint8_t pk_bin[PK_RAW_SIZE], pk_username[MAX_NAME]; uint8_t pk_bin[PK_ED25519_SIZE], pk_username[MAX_NAME];
memcpy(pk_bin, pkt->data, PK_RAW_SIZE); memcpy(pk_bin, pkt->data, PK_ED25519_SIZE);
memcpy(pk_username, pkt->data + PK_RAW_SIZE, MAX_NAME); memcpy(pk_username, pkt->data + PK_ED25519_SIZE, MAX_NAME);
if (crypto_sign_verify_detached(pkt->signature, challenge, CHALLENGE_SIZE, if (crypto_sign_verify_detached(pkt->signature, challenge, CHALLENGE_SIZE,
pk_bin) != 0) { pk_bin) != 0) {