Skip to content

Commit cb0d54e

Browse files
committed
feat: add new availability features
1 parent 12629c8 commit cb0d54e

File tree

6 files changed

+42
-30
lines changed

6 files changed

+42
-30
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
__pycache__/
22
account.coldwire
33
*.swp
4+
*.swo
45
TODO.md
56
TODO.txt

core/constants.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@
66
ACCOUNT_FILE_PATH = "account.coldwire"
77

88
# Coldwire protocol misc (bytes)
9-
SMP_TYPE = b"\x00"
10-
PFS_TYPE = b"\x01"
11-
MSG_TYPE = b"\x02"
9+
SMP_TYPES = {
10+
"SMP_INIT": b"\x00"
11+
}
12+
PFS_TYPES = {
13+
"PFS_NEW": b"\x01",
14+
"PFS_ACK": b"\x02",
15+
}
16+
17+
MSG_TYPES = {
18+
"MSG_BATCH": b"\x03",
19+
"MSG_NEW": b"\x04"
20+
}
1221

1322
COLDWIRE_DATA_SEP = b"\0"
1423
COLDWIRE_LEN_OFFSET = 3

logic/background_worker.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
LONGPOLL_MIN,
88
LONGPOLL_MAX,
99
COLDWIRE_LEN_OFFSET,
10-
SMP_TYPE,
11-
PFS_TYPE,
12-
MSG_TYPE,
10+
SMP_TYPES,
11+
PFS_TYPES,
12+
MSG_TYPES,
1313
XCHACHA20POLY1305_NONCE_LEN
1414
)
1515
from core.crypto import random_number_range
@@ -162,16 +162,16 @@ def background_worker(user_data, user_data_lock, ui_queue, stop_flag):
162162

163163

164164
# SMP
165-
if bytes([blob_plaintext[0]]) == SMP_TYPE:
166-
smp_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext[1:])
165+
if bytes([blob_plaintext[0]]) in SMP_TYPES.values():
166+
smp_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext)
167167

168168
# PFS
169-
elif bytes([blob_plaintext[0]]) == PFS_TYPE:
170-
pfs_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext[1:])
169+
elif bytes([blob_plaintext[0]]) in PFS_TYPES.values():
170+
pfs_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext)
171171

172172
# MSG
173-
elif bytes([blob_plaintext[0]]) == MSG_TYPE:
174-
messages_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext[1:])
173+
elif bytes([blob_plaintext[0]]) in MSG_TYPES.values():
174+
messages_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, sender, blob_plaintext)
175175

176176
else:
177177
logger.error(

logic/message.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
otp_decrypt_with_padding
2929
)
3030
from core.constants import (
31-
MSG_TYPE,
31+
MSG_TYPES,
3232
OTP_MAX_BUCKET,
3333
OTP_PAD_SIZE,
3434
ML_KEM_1024_NAME,
@@ -81,7 +81,7 @@ def generate_and_send_pads(user_data, user_data_lock, contact_id: str, ui_queue)
8181
our_new_strand_nonce = sha3_512(secrets.token_bytes(XCHACHA20POLY1305_NONCE_LEN))[:XCHACHA20POLY1305_NONCE_LEN]
8282
_, ciphertext_blob = encrypt_xchacha20poly1305(
8383
our_strand_key,
84-
MSG_TYPE + b"\x00" + our_new_strand_nonce + otp_batch_signature + kyber_ciphertext_blob + mceliece_ciphertext_blob + xchacha_shared_secrets,
84+
MSG_TYPES["MSG_BATCH"] + our_new_strand_nonce + otp_batch_signature + kyber_ciphertext_blob + mceliece_ciphertext_blob + xchacha_shared_secrets,
8585
nonce = our_next_strand_nonce
8686
)
8787

@@ -203,7 +203,7 @@ def send_message_processor(user_data, user_data_lock, contact_id: str, message:
203203

204204
_, ciphertext_blob = encrypt_xchacha20poly1305(
205205
our_strand_key,
206-
MSG_TYPE + b"\x01" + our_new_strand_nonce + message_encrypted,
206+
MSG_TYPES["MSG_NEW"] + our_new_strand_nonce + message_encrypted,
207207
nonce = our_next_strand_nonce
208208
)
209209

@@ -257,7 +257,7 @@ def messages_data_handler(user_data: dict, user_data_lock, user_data_copied: dic
257257

258258

259259

260-
if msgs_plaintext[0] == 0:
260+
if bytes([msgs_plaintext[0]]) == MSG_TYPES["MSG_BATCH"]:
261261
logger.debug("Received a new OTP pads batch from contact (%s).", contact_id)
262262

263263
# /32 because KEM shared_secret is 32 bytes, /64 because sha3_512 output is 64 bytes
@@ -328,7 +328,7 @@ def messages_data_handler(user_data: dict, user_data_lock, user_data_copied: dic
328328

329329

330330

331-
elif msgs_plaintext[0] == 1:
331+
elif bytes([msgs_plaintext[0]]) == MSG_TYPES["MSG_NEW"]:
332332
logger.debug("Received a new message from contact (%s).", contact_id)
333333

334334
if len(msgs_plaintext) < OTP_MAX_BUCKET + XCHACHA20POLY1305_NONCE_LEN + 1:

logic/pfs.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
random_number_range
2020
)
2121
from core.constants import (
22-
PFS_TYPE,
22+
PFS_TYPES,
2323
ML_KEM_1024_NAME,
2424
ML_DSA_87_NAME,
2525
ML_KEM_1024_PK_LEN,
@@ -60,7 +60,7 @@ def send_pfs_ack(user_data: dict, user_data_lock: threading.Lock, contact_id: st
6060
our_new_strand_nonce = sha3_512(secrets.token_bytes(XCHACHA20POLY1305_NONCE_LEN))[:XCHACHA20POLY1305_NONCE_LEN]
6161
_, ciphertext_blob = encrypt_xchacha20poly1305(
6262
our_strand_key,
63-
PFS_TYPE + b"\x01" + our_new_strand_nonce,
63+
PFS_TYPES["PFS_ACK"] + our_new_strand_nonce,
6464
nonce = our_next_strand_nonce
6565
)
6666

@@ -148,7 +148,7 @@ def send_new_ephemeral_keys(user_data: dict, user_data_lock: threading.Lock, con
148148
our_new_strand_nonce = sha3_512(secrets.token_bytes(XCHACHA20POLY1305_NONCE_LEN))[:XCHACHA20POLY1305_NONCE_LEN]
149149
_, ciphertext_blob = encrypt_xchacha20poly1305(
150150
our_strand_key,
151-
PFS_TYPE + b"\x00" + our_new_strand_nonce + publickeys_hashchain_signature + publickeys_hashchain,
151+
PFS_TYPES["PFS_NEW"] + our_new_strand_nonce + publickeys_hashchain_signature + publickeys_hashchain,
152152
nonce = our_next_strand_nonce,
153153
max_padding = 1024
154154
)
@@ -234,15 +234,15 @@ def pfs_data_handler(user_data: dict, user_data_lock: threading.Lock, user_data_
234234
logger.error("Contact (%s) strand key key is missing! Skipping message...", contact_id)
235235
return
236236

237-
if pfs_plaintext[0] == 1:
237+
if bytes([pfs_plaintext[0]]) == PFS_TYPES["PFS_ACK"]:
238238
logger.info("Received acknowlegement of PFS keys from contact %s", contact_id)
239239
with user_data_lock:
240240
user_data["contacts"][contact_id]["contact_next_strand_nonce"] = pfs_plaintext[1:]
241241

242242
user_data["contacts"][contact_id]["ephemeral_keys"]["our_keys"][ML_KEM_1024_NAME]["private_key"] = user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][ML_KEM_1024_NAME]["private_key"]
243243
user_data["contacts"][contact_id]["ephemeral_keys"]["our_keys"][ML_KEM_1024_NAME]["public_key"] = user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][ML_KEM_1024_NAME]["public_key"]
244244

245-
if user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][ML_KEM_1024_NAME]["private_key"]:
245+
if user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][CLASSIC_MCELIECE_8_F_NAME]["private_key"]:
246246
user_data["contacts"][contact_id]["ephemeral_keys"]["our_keys"][CLASSIC_MCELIECE_8_F_NAME]["private_key"] = user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][CLASSIC_MCELIECE_8_F_NAME]["private_key"]
247247
user_data["contacts"][contact_id]["ephemeral_keys"]["our_keys"][CLASSIC_MCELIECE_8_F_NAME]["public_key"] = user_data["contacts"][contact_id]["ephemeral_keys"]["staged_keys"][CLASSIC_MCELIECE_8_F_NAME]["public_key"]
248248

@@ -255,7 +255,7 @@ def pfs_data_handler(user_data: dict, user_data_lock: threading.Lock, user_data_
255255
save_account_data(user_data, user_data_lock)
256256
return
257257

258-
elif pfs_plaintext[0] == 0:
258+
elif bytes([pfs_plaintext[0]]) == PFS_TYPES["PFS_NEW"]:
259259
pfs_plaintext = pfs_plaintext[1:]
260260
else:
261261
logger.error("Skipping unknown PFS of type (%d) from contact (%s)", pfs_plaintext[0], contact_id)

logic/smp.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
)
3131
from base64 import b64encode, b64decode
3232
from core.constants import (
33-
SMP_TYPE,
33+
SMP_TYPES,
3434
SMP_NONCE_LENGTH,
3535
SMP_PROOF_LENGTH,
3636
SMP_QUESTION_MAX_LEN,
@@ -75,7 +75,7 @@ def initiate_smp(user_data: dict, user_data_lock: threading.Lock, contact_id: st
7575
"recipient": contact_id
7676
},
7777
headers = session_headers,
78-
blob = SMP_TYPE + kem_public_key,
78+
blob = SMP_TYPES["SMP_INIT"] + kem_public_key,
7979
auth_token = auth_token
8080
)
8181
except Exception as e:
@@ -136,7 +136,7 @@ def smp_step_2(user_data: dict, user_data_lock, contact_id: str, blob: bytes, ui
136136
http_request(f"{server_url}/data/send", "POST", metadata = {
137137
"recipient": contact_id
138138
},
139-
blob = SMP_TYPE + key_ciphertext + ciphertext_nonce + ciphertext_blob,
139+
blob = SMP_TYPES["SMP_INIT"] + key_ciphertext + ciphertext_nonce + ciphertext_blob,
140140
headers = session_headers,
141141
auth_token = auth_token
142142
)
@@ -215,7 +215,7 @@ def smp_step_3(user_data: dict, user_data_lock: threading.Lock, contact_id: str,
215215
our_new_strand_nonce = sha3_512(secrets.token_bytes(XCHACHA20POLY1305_NONCE_LEN))[:XCHACHA20POLY1305_NONCE_LEN]
216216
_, ciphertext_blob = encrypt_xchacha20poly1305(
217217
chacha_key,
218-
SMP_TYPE + our_new_strand_nonce + signing_public_key + our_nonce + our_proof + question.encode("utf-8"),
218+
SMP_TYPES["SMP_INIT"] + our_new_strand_nonce + signing_public_key + our_nonce + our_proof + question.encode("utf-8"),
219219
nonce = our_next_strand_nonce
220220
)
221221

@@ -348,7 +348,7 @@ def smp_step_4_answer_provided(user_data, user_data_lock, contact_id, answer, ui
348348
our_new_strand_nonce = sha3_512(secrets.token_bytes(XCHACHA20POLY1305_NONCE_LEN))[:XCHACHA20POLY1305_NONCE_LEN]
349349
_, ciphertext_blob = encrypt_xchacha20poly1305(
350350
tmp_key,
351-
SMP_TYPE + our_new_strand_nonce + our_proof + our_strand_key + contact_strand_key,
351+
SMP_TYPES["SMP_INIT"] + our_new_strand_nonce + our_proof + our_strand_key + contact_strand_key,
352352
nonce = our_next_strand_nonce
353353
)
354354

@@ -513,7 +513,7 @@ def smp_failure_notify_contact(user_data, user_data_lock, contact_id, ui_queue)
513513
# it can be any number other than 2, we chose 7 because failure is *technically* the 7th smp step.
514514
ciphertext_nonce, ciphertext_blob = encrypt_xchacha20poly1305(
515515
tmp_key,
516-
SMP_TYPE + b"failure",
516+
SMP_TYPES["SMP_INIT"] + b"failure",
517517
counter = 7
518518
)
519519
try:
@@ -550,12 +550,14 @@ def smp_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, cont
550550
except Exception:
551551
smp_step = 2
552552

553-
554553

555554
if user_data_copied["settings"]["ignore_new_contacts_smp"]:
556555
logger.info("Skipping SMP request because you have set to ignore new contacts requests.")
557556
return
558557

558+
559+
# TEMPORARIY, UNTIL WE REWORK SMP STEP HANDLING
560+
message = message[1:]
559561

560562

561563
if message == b"failure":

0 commit comments

Comments
 (0)