1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! Cryptographic constants for JACS.
//!
//! This module centralizes all magic numbers used in cryptographic operations,
//! making them easier to audit, update, and understand.
// ============================================================================
// AES-GCM Constants
// ============================================================================
/// AES-256 key size in bytes (256 bits).
pub const AES_256_KEY_SIZE: usize = 32;
/// AES-GCM nonce size in bytes (96 bits as recommended by NIST SP 800-38D).
pub const AES_GCM_NONCE_SIZE: usize = 12;
/// Salt length for password-based key derivation in bytes.
/// 128 bits provides sufficient entropy to prevent rainbow table attacks.
pub const PBKDF2_SALT_SIZE: usize = 16;
/// Minimum encrypted data size: salt (16) + nonce (12) = 28 bytes.
/// Any encrypted payload must be at least this size to contain the header.
pub const MIN_ENCRYPTED_HEADER_SIZE: usize = PBKDF2_SALT_SIZE + AES_GCM_NONCE_SIZE;
// ============================================================================
// PBKDF2 / Password Derivation Constants
// ============================================================================
/// Number of PBKDF2 iterations for key derivation.
/// 600,000 iterations per OWASP 2024 recommendation for PBKDF2-HMAC-SHA256.
/// This adds approximately 19.2 bits of work factor.
pub const PBKDF2_ITERATIONS: u32 = 600_000;
/// Legacy iteration count for migration from pre-0.6.0 keys.
pub const PBKDF2_ITERATIONS_LEGACY: u32 = 100_000;
/// Minimum password length for key encryption.
pub const MIN_PASSWORD_LENGTH: usize = 8;
/// Minimum entropy bits required for a password.
/// 28 bits provides reasonable protection against offline attacks when combined
/// with PBKDF2's 100k iterations (which effectively adds ~17 bits of work factor).
pub const MIN_ENTROPY_BITS: f64 = 28.0;
/// Entropy threshold for single character class passwords.
/// Passwords using only one character class (e.g., all lowercase) must have
/// at least this many bits of entropy to compensate for lack of variety.
pub const SINGLE_CLASS_MIN_ENTROPY_BITS: f64 = 35.0;
// ============================================================================
// Password Pattern Detection Constants
// ============================================================================
/// Maximum consecutive identical characters allowed before rejection.
/// 4 or more identical characters in a row (e.g., "aaaa") is rejected.
pub const MAX_CONSECUTIVE_IDENTICAL_CHARS: usize = 4;
/// Maximum sequential characters allowed before rejection.
/// 5 or more sequential characters (e.g., "12345" or "abcde") is rejected.
pub const MAX_SEQUENTIAL_CHARS: usize = 5;
// ============================================================================
// Entropy Calculation Constants (Character Pool Sizes)
// ============================================================================
/// Number of lowercase letters in English alphabet (a-z).
pub const LOWERCASE_POOL_SIZE: usize = 26;
/// Number of uppercase letters in English alphabet (A-Z).
pub const UPPERCASE_POOL_SIZE: usize = 26;
/// Number of digits (0-9).
pub const DIGIT_POOL_SIZE: usize = 10;
/// Approximate number of common special characters.
pub const SPECIAL_CHAR_POOL_SIZE: usize = 32;
/// Uniqueness ratio threshold for severe entropy penalty.
/// Passwords with less than 50% unique characters get a 0.5x penalty.
pub const SEVERE_UNIQUENESS_THRESHOLD: f64 = 0.5;
/// Uniqueness ratio threshold for moderate entropy penalty.
/// Passwords with 50-75% unique characters get a 0.75x penalty.
pub const MODERATE_UNIQUENESS_THRESHOLD: f64 = 0.75;
/// Severe penalty multiplier for low uniqueness passwords.
pub const SEVERE_UNIQUENESS_PENALTY: f64 = 0.5;
/// Moderate penalty multiplier for medium uniqueness passwords.
pub const MODERATE_UNIQUENESS_PENALTY: f64 = 0.75;
// ============================================================================
// RSA Constants
// ============================================================================
/// RSA key size in bits for production use.
/// 4096 bits provides security margin beyond current recommendations.
pub const RSA_KEY_BITS: usize = 4096;
/// RSA key size in bits for test use only.
/// 2048 bits is faster for tests while still being cryptographically valid.
pub const RSA_TEST_KEY_BITS: usize = 2048;
// ============================================================================
// Ed25519 Constants
// ============================================================================
/// Ed25519 public key size in bytes.
pub const ED25519_PUBLIC_KEY_SIZE: usize = 32;
// ============================================================================
// ML-KEM-768 (FIPS-203) Constants
// ============================================================================
/// ML-KEM-768 encapsulation key (public key) size in bytes.
pub const ML_KEM_768_ENCAPS_KEY_SIZE: usize = 1184;
/// ML-KEM-768 decapsulation key (private key) size in bytes.
pub const ML_KEM_768_DECAPS_KEY_SIZE: usize = 2400;
/// ML-KEM-768 ciphertext size in bytes.
pub const ML_KEM_768_CIPHERTEXT_SIZE: usize = 1088;
// ============================================================================
// ML-DSA-87 (FIPS-204) Constants
// ============================================================================
/// ML-DSA-87 private key size in bytes.
pub const ML_DSA_87_PRIVATE_KEY_SIZE: usize = 4896;
/// ML-DSA-87 public key size in bytes.
pub const ML_DSA_87_PUBLIC_KEY_SIZE: usize = 2592;
/// ML-DSA-87 signature size in bytes.
pub const ML_DSA_87_SIGNATURE_SIZE: usize = 4627;
// ============================================================================
// Algorithm Detection Heuristic Constants
// ============================================================================
/// Minimum key length (in bytes) to consider for RSA detection.
pub const RSA_MIN_KEY_LENGTH: usize = 100;
/// Minimum key length (in bytes) to consider for Dilithium detection.
pub const DILITHIUM_MIN_KEY_LENGTH: usize = 1000;
/// Non-ASCII ratio threshold for Ed25519 detection.
/// Ed25519 keys typically have high non-ASCII content (>50%).
pub const ED25519_NON_ASCII_RATIO: f32 = 0.5;
/// Non-ASCII ratio threshold below which RSA is likely.
/// RSA PEM keys are mostly ASCII (<20% non-ASCII).
pub const RSA_NON_ASCII_RATIO: f32 = 0.2;
/// Non-ASCII ratio threshold for Dilithium detection.
/// Dilithium keys have significant non-ASCII content (>30%).
pub const DILITHIUM_NON_ASCII_RATIO: f32 = 0.3;
/// Key length threshold for distinguishing small PQ keys.
pub const PQ_SMALL_KEY_THRESHOLD: usize = 500;
// ============================================================================
// Dilithium Signature Size Detection
// ============================================================================
/// Lower bound for alternative Dilithium signature size detection.
pub const DILITHIUM_ALT_SIG_SIZE_MIN: usize = 4640;
/// Upper bound for alternative Dilithium signature size detection.
pub const DILITHIUM_ALT_SIG_SIZE_MAX: usize = 4650;
// ============================================================================
// HKDF Domain Separation
// ============================================================================
/// HKDF info string for JACS PQ2025 AEAD key derivation.
pub const HKDF_INFO_JACS_PQ2025_AEAD: & = b"jacs-pq2025-aead";