@@ -71,14 +71,19 @@ def generate_and_send_pads(user_data, user_data_lock, contact_id: str, ui_queue)
7171 kyber_ciphertext_blob , kyber_shared_secrets = generate_shared_secrets (contact_kyber_public_key , ML_KEM_1024_NAME )
7272 mceliece_ciphertext_blob , mceliece_shared_secrets = generate_shared_secrets (contact_mceliece_public_key , CLASSIC_MCELIECE_8_F_NAME )
7373
74+ xchacha_shared_secrets = b''
75+ while len (xchacha_shared_secrets ) < OTP_PAD_SIZE :
76+ xchacha_shared_secrets += sha3_512 (secrets .token_bytes (64 ))
77+
78+
7479 otp_batch_signature = create_signature (ML_DSA_87_NAME , kyber_ciphertext_blob + mceliece_ciphertext_blob , our_lt_private_key )
7580
7681 hash_chain_seed = sha3_512 (secrets .token_bytes (MESSAGE_HASH_CHAIN_LEN ))
7782
7883 our_new_strand_nonce = sha3_512 (secrets .token_bytes (XCHACHA20POLY1305_NONCE_LEN ))[:XCHACHA20POLY1305_NONCE_LEN ]
7984 _ , ciphertext_blob = encrypt_xchacha20poly1305 (
8085 our_strand_key ,
81- MSG_TYPE + b"\x00 " + our_new_strand_nonce + hash_chain_seed + otp_batch_signature + kyber_ciphertext_blob + mceliece_ciphertext_blob ,
86+ MSG_TYPE + b"\x00 " + our_new_strand_nonce + hash_chain_seed + otp_batch_signature + kyber_ciphertext_blob + mceliece_ciphertext_blob + xchacha_shared_secrets ,
8287 nonce = our_next_strand_nonce
8388 )
8489
@@ -95,6 +100,7 @@ def generate_and_send_pads(user_data, user_data_lock, contact_id: str, ui_queue)
95100 return False
96101
97102 pads , _ = one_time_pad (kyber_shared_secrets , mceliece_shared_secrets )
103+ pads , _ = one_time_pad (pads , xchacha_shared_secrets )
98104
99105
100106 our_strand_key = pads [:32 ]
@@ -265,12 +271,16 @@ def messages_data_handler(user_data: dict, user_data_lock, user_data_copied: dic
265271 if msgs_plaintext [0 ] == 0 :
266272 logger .debug ("Received a new OTP pads batch from contact (%s)." , contact_id )
267273
268- if len (msgs_plaintext ) != ( (ML_KEM_1024_CT_LEN + CLASSIC_MCELIECE_8_F_CT_LEN ) * (OTP_PAD_SIZE // 32 )) + ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 :
274+ # /32 because KEM shared_secret is 32 bytes, /64 because sha3_512 output is 64 bytes
275+
276+ if len (msgs_plaintext ) != ( (ML_KEM_1024_CT_LEN + CLASSIC_MCELIECE_8_F_CT_LEN ) * (OTP_PAD_SIZE // 32 )) + (64 * (OTP_PAD_SIZE // 64 )) + ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 :
269277 logger .error ("Contact (%s) gave us a otp batch message request with malformed strand plaintext length (%d)" , contact_id , len (msgs_plaintext ))
270278 return
271279
272280 otp_hashchain_signature = msgs_plaintext [1 + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN : MESSAGE_HASH_CHAIN_LEN + ML_DSA_87_SIGN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 ]
273- otp_hashchain_ciphertext = msgs_plaintext [ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 :]
281+ otp_hashchain_ciphertext = msgs_plaintext [ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 : ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 + ((ML_KEM_1024_CT_LEN + CLASSIC_MCELIECE_8_F_CT_LEN ) * (OTP_PAD_SIZE // 32 ))]
282+
283+ xchacha_pads = msgs_plaintext [ML_DSA_87_SIGN_LEN + MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 + ((ML_KEM_1024_CT_LEN + CLASSIC_MCELIECE_8_F_CT_LEN ) * (OTP_PAD_SIZE // 32 )):]
274284
275285 contact_hash_chain = msgs_plaintext [1 + XCHACHA20POLY1305_NONCE_LEN : MESSAGE_HASH_CHAIN_LEN + XCHACHA20POLY1305_NONCE_LEN + 1 ]
276286
@@ -286,7 +296,6 @@ def messages_data_handler(user_data: dict, user_data_lock, user_data_copied: dic
286296 our_kyber_key = user_data_copied ["contacts" ][contact_id ]["ephemeral_keys" ]["our_keys" ][ML_KEM_1024_NAME ]["private_key" ]
287297 our_mceliece_key = user_data_copied ["contacts" ][contact_id ]["ephemeral_keys" ]["our_keys" ][CLASSIC_MCELIECE_8_F_NAME ]["private_key" ]
288298
289- # / 32 because shared secret is 32 bytes
290299 try :
291300 contact_kyber_pads = decrypt_shared_secrets (otp_hashchain_ciphertext [:ML_KEM_1024_CT_LEN * (OTP_PAD_SIZE // 32 )], our_kyber_key , ML_KEM_1024_NAME )
292301 except Exception as e :
@@ -300,6 +309,8 @@ def messages_data_handler(user_data: dict, user_data_lock, user_data_copied: dic
300309 return
301310
302311 contact_pads , _ = one_time_pad (contact_kyber_pads , contact_mceliece_pads )
312+ contact_pads , _ = one_time_pad (contact_pads , xchacha_pads )
313+
303314 contact_strand_key = contact_pads [:32 ]
304315 contact_pads = contact_pads [32 :]
305316
0 commit comments