Skip to content

Commit 27cefc3

Browse files
committed
refactor: Replace hard-coded numbers with shared constants
1 parent 1d75ce3 commit 27cefc3

File tree

6 files changed

+25
-18
lines changed

6 files changed

+25
-18
lines changed

core/constants.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616
OTP_PADDING_LENGTH = 2
1717
OTP_PADDING_LIMIT = 1024
1818

19+
SMP_NONCE_LENGTH = 64
20+
SMP_PROOF_LENGTH = 64
21+
SMP_QUESTION_MAX_LEN = 500
22+
1923
# NIST-specified key sizes (bytes) and metadata
20-
ML_KEM_1024_NAME = "Kyber1024"
24+
ML_KEM_1024_NAME = "ML-KEM-1024"
2125
ML_KEM_1024_SK_LEN = 3168
2226
ML_KEM_1024_PK_LEN = 1568
2327
ML_KEM_1024_CT_LEN = 1568
2428

2529

26-
ML_DSA_87_NAME = "Dilithium5"
30+
ML_DSA_87_NAME = "ML-DSA-87"
2731
ML_DSA_87_SK_LEN = 4864
2832
ML_DSA_87_PK_LEN = 2592
2933
ML_DSA_87_SIGN_LEN = 4595

core/crypto.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@
44
Post-quantum cryptographic operations for Coldwire.
55
66
Implements:
7-
- Key generation (ML-KEM-1024 / Kyber, ML-DSA-87 / Dilithium5)
7+
- Key generation (ML-KEM-1024, ML-DSA-87, Classic-McEliece-8192128f)
88
- Signature creation and verification
99
- One-Time Pad (OTP) encryption with padding
10-
- Kyber-based OTP key exchange
10+
- Retrieving shared secrets from KEM chunks
1111
- Secure random number generation
12-
13-
Notes:
14-
- Kyber keys and ciphertext sizes follow NIST spec for ML-KEM-1024.
15-
- Dilithium5 keys/signature sizes follow NIST spec for ML-DSA-87.
16-
- OTP padding randomizes message lengths to resist ciphertext length analysis.
12+
- OTP padding
1713
"""
1814

1915
import oqs
@@ -37,7 +33,7 @@ def create_signature(algorithm: str, message: bytes, private_key: bytes) -> byte
3733
Creates a digital signature for a message using a post-quantum signature scheme.
3834
3935
Args:
40-
algorithm: PQ signature algorithm (e.g. "Dilithium5").
36+
algorithm: PQ signature algorithm (e.g. "ML-DSA-87").
4137
message: Data to sign.
4238
private_key: Private key bytes.
4339
@@ -52,7 +48,7 @@ def verify_signature(algorithm: str, message: bytes, signature: bytes, public_ke
5248
Verifies a post-quantum signature.
5349
5450
Args:
55-
algorithm: PQ signature algorithm (e.g. "Dilithium5").
51+
algorithm: PQ signature algorithm (e.g. "ML-DSA-87").
5652
message: Original message data.
5753
signature: Signature to verify.
5854
public_key: Corresponding public key bytes.
@@ -68,7 +64,7 @@ def generate_sign_keys(algorithm: str = ML_DSA_87_NAME):
6864
Generates a new post-quantum signature keypair.
6965
7066
Args:
71-
algorithm: PQ signature algorithm (default ML-DSA-87 / Dilithium5).
67+
algorithm: PQ signature algorithm (default ML-DSA-87).
7268
7369
Returns:
7470
(private_key, public_key) as bytes.

logic/authentication.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from base64 import b64encode, b64decode
22
from core.requests import http_request
33
from core.crypto import create_signature
4+
from core.constants import (
5+
ML_DSA_87_NAME
6+
)
47

58
def authenticate_account(user_data: dict) -> dict:
69
url = user_data["server_url"]
@@ -27,7 +30,7 @@ def authenticate_account(user_data: dict) -> dict:
2730
raise ValueError("Server gave a malformed challenge! Are you sure this is Coldwire server ?")
2831

2932

30-
signature = create_signature("Dilithium5", challenge, private_key)
33+
signature = create_signature(ML_DSA_87_NAME, challenge, private_key)
3134

3235
try:
3336
response = http_request(url + "/authenticate/verify", "POST", payload = {"signature": b64encode(signature).decode(), "challenge": response["challenge"]})

logic/pfs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from core.constants import (
1010
ALGOS_BUFFER_LIMITS,
1111
ML_KEM_1024_NAME,
12+
ML_DSA_87_NAME,
1213
CLASSIC_MCELIECE_8_F_NAME,
1314
CLASSIC_MCELIECE_8_F_ROTATE_AT
1415
)
@@ -57,7 +58,7 @@ def send_new_ephemeral_keys(user_data, user_data_lock, contact_id, ui_queue) ->
5758
pfs_type = "full"
5859

5960
# Sign them with our per-contact long-term private key
60-
publickeys_hashchain_signature = create_signature("Dilithium5", publickeys_hashchain, lt_sign_private_key)
61+
publickeys_hashchain_signature = create_signature(ML_DSA_87_NAME, publickeys_hashchain, lt_sign_private_key)
6162

6263
payload = {
6364
"publickeys_hashchain": b64encode(publickeys_hashchain).decode(),
@@ -147,7 +148,7 @@ def pfs_data_handler(user_data, user_data_lock, user_data_copied, ui_queue, mess
147148
contact_hashchain_signature = b64decode(message["hashchain_signature"], validate=True)
148149
contact_publickeys_hashchain = b64decode(message["publickeys_hashchain"], validate=True)
149150

150-
valid_signature = verify_signature("Dilithium5", contact_publickeys_hashchain, contact_hashchain_signature, contact_lt_public_key)
151+
valid_signature = verify_signature(ML_DSA_87_NAME, contact_publickeys_hashchain, contact_hashchain_signature, contact_lt_public_key)
151152
if not valid_signature:
152153
logger.error("Invalid ephemeral public-key + hashchain signature from contact (%s)", contact_id)
153154
return

logic/smp.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
from core.crypto import generate_sign_keys
4040
from core.trad_crypto import derive_key_argon2id, sha3_512
4141
from base64 import b64encode, b64decode
42+
from core.constants import (
43+
SMP_NONCE_LENGTH
44+
)
4245
import hashlib
4346
import secrets
4447
import hmac
@@ -58,7 +61,7 @@ def initiate_smp(user_data: dict, user_data_lock, contact_id: str, question: str
5861
server_url = user_data["server_url"]
5962
auth_token = user_data["token"]
6063

61-
our_nonce = b64encode(secrets.token_bytes(32)).decode()
64+
our_nonce = b64encode(secrets.token_bytes(SMP_NONCE_LENGTH)).decode()
6265

6366
private_key, public_key = generate_sign_keys()
6467

@@ -99,7 +102,7 @@ def initiate_smp(user_data: dict, user_data_lock, contact_id: str, question: str
99102
def smp_step_2_answer_provided(user_data, user_data_lock, contact_id, answer, ui_queue) -> None:
100103
answer = normalize_answer(answer)
101104

102-
our_nonce = secrets.token_bytes(32)
105+
our_nonce = secrets.token_bytes(SMP_NONCE_LENGTH)
103106

104107
private_key, public_key = generate_sign_keys()
105108

tests/test_crypto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def test_mldsa_keygen_basic():
112112

113113
def test_signature_verifcation():
114114
"""Validate ML-DSA-87 signature creation and verification"""
115-
private_key, public_key = generate_sign_keys(algorithm="Dilithium5")
115+
private_key, public_key = generate_sign_keys(algorithm=ML_DSA_87_NAME)
116116

117117
assert private_key != public_key, "Private and public keys are identical"
118118

0 commit comments

Comments
 (0)