nexus-crypt 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,241 @@
1
+ """Unit tests for mathematical utilities"""
2
+
3
+ import pytest
4
+ import secrets
5
+ from nexus.math_utils import (
6
+ rol, ror, bytes_to_words, words_to_bytes,
7
+ gf128_multiply, generate_lwe_sbox, generate_ntru_permutation,
8
+ hkdf_sha256, ensure_bijection
9
+ )
10
+ from nexus.constants import SBOX_SIZE, NTRU_N
11
+
12
+ class TestRotationOperations:
13
+ """Test rotation operations"""
14
+
15
+ def test_rotate_left(self):
16
+ """Test left rotation"""
17
+ value = 0b1010
18
+ rotated = rol(value, 1, bits=4)
19
+ assert rotated == 0b0101
20
+
21
+ def test_rotate_right(self):
22
+ """Test right rotation"""
23
+ value = 0b1010
24
+ rotated = ror(value, 1, bits=4)
25
+ assert rotated == 0b0101
26
+
27
+ def test_rotate_left_wraparound(self):
28
+ """Test left rotation with wraparound"""
29
+ value = 0b1000
30
+ rotated = rol(value, 1, bits=4)
31
+ assert rotated == 0b0001
32
+
33
+ def test_rotate_128bit(self):
34
+ """Test 128-bit rotation"""
35
+ value = (1 << 127) # MSB set
36
+ rotated = rol(value, 1, bits=128)
37
+ assert rotated == 1 # Wrapped to LSB
38
+
39
+ def test_rotation_identity(self):
40
+ """Test that rotating by full width returns original"""
41
+ value = 0xABCD
42
+ rotated = rol(value, 128, bits=128)
43
+ assert rotated == value
44
+
45
+
46
+ class TestWordConversion:
47
+ """Test byte/word conversion"""
48
+
49
+ def test_bytes_to_words(self):
50
+ """Test converting bytes to 128-bit words"""
51
+ data = b'\x00' * 16 + b'\xFF' * 16
52
+ words = bytes_to_words(data)
53
+
54
+ assert len(words) == 2
55
+ assert words[0] == 0
56
+ assert words[1] == (1 << 128) - 1
57
+
58
+ def test_words_to_bytes(self):
59
+ """Test converting words back to bytes"""
60
+ words = [0xABCD, 0x1234]
61
+ data = words_to_bytes(words)
62
+
63
+ assert len(data) == 32
64
+ assert bytes_to_words(data) == words
65
+
66
+ def test_round_trip_conversion(self):
67
+ """Test round-trip byte <-> word conversion"""
68
+ original = secrets.token_bytes(64)
69
+ words = bytes_to_words(original)
70
+ recovered = words_to_bytes(words)
71
+
72
+ assert recovered == original
73
+
74
+
75
+ class TestGaloisFieldArithmetic:
76
+ """Test GF(2^128) operations"""
77
+
78
+ def test_gf128_multiply_zero(self):
79
+ """Test multiplication by zero"""
80
+ a = 0xFFFFFFFF
81
+ result = gf128_multiply(a, 0)
82
+ assert result == 0
83
+
84
+ def test_gf128_multiply_one(self):
85
+ """Test multiplication by one (identity)"""
86
+ a = 0x123456789ABCDEF
87
+ result = gf128_multiply(a, 1)
88
+ assert result == a
89
+
90
+ def test_gf128_multiply_commutativity(self):
91
+ """Test that multiplication is commutative"""
92
+ a = 0xABCD1234
93
+ b = 0x5678EF12 # Random value
94
+
95
+ result1 = gf128_multiply(a, b)
96
+ result2 = gf128_multiply(b, a)
97
+
98
+ assert result1 == result2
99
+
100
+ def test_gf128_multiply_produces_valid_result(self):
101
+ """Test that result fits in 128 bits"""
102
+ a = (1 << 127) # Large value
103
+ b = (1 << 127)
104
+
105
+ result = gf128_multiply(a, b)
106
+ assert result < (1 << 128)
107
+
108
+
109
+ class TestLWESbox:
110
+ """Test LWE S-box generation"""
111
+
112
+ def test_sbox_correct_size(self):
113
+ """Test S-box has correct size"""
114
+ key = secrets.token_bytes(32)
115
+ sbox = generate_lwe_sbox(key, 0, 0)
116
+
117
+ assert len(sbox) == SBOX_SIZE
118
+
119
+ def test_sbox_is_bijection(self):
120
+ """Test S-box is a valid permutation"""
121
+ key = secrets.token_bytes(32)
122
+ sbox = generate_lwe_sbox(key, 0, 0)
123
+
124
+ # All values should be unique
125
+ assert len(set(sbox)) == SBOX_SIZE
126
+ # All values in range [0, 255]
127
+ assert all(0 <= v < 256 for v in sbox)
128
+
129
+ def test_sbox_deterministic(self):
130
+ """Test S-box generation is deterministic"""
131
+ key = secrets.token_bytes(32)
132
+
133
+ sbox1 = generate_lwe_sbox(key, 0, 0)
134
+ sbox2 = generate_lwe_sbox(key, 0, 0)
135
+
136
+ assert sbox1 == sbox2
137
+
138
+ def test_different_keys_produce_different_sboxes(self):
139
+ """Test different keys produce different S-boxes"""
140
+ key1 = secrets.token_bytes(32)
141
+ key2 = secrets.token_bytes(32)
142
+
143
+ sbox1 = generate_lwe_sbox(key1, 0, 0)
144
+ sbox2 = generate_lwe_sbox(key2, 0, 0)
145
+
146
+ assert sbox1 != sbox2
147
+
148
+ def test_different_counters_produce_different_sboxes(self):
149
+ """Test different counters regenerate S-boxes"""
150
+ key = secrets.token_bytes(32)
151
+
152
+ sbox1 = generate_lwe_sbox(key, 0, 0)
153
+ sbox2 = generate_lwe_sbox(key, 0, 1)
154
+
155
+ assert sbox1 != sbox2
156
+
157
+ def test_ensure_bijection_fixes_duplicates(self):
158
+ """Test bijection enforcement"""
159
+ # Create list with duplicates
160
+ sbox = list(range(256))
161
+ sbox[5] = sbox[10] # Create duplicate
162
+
163
+ fixed = ensure_bijection(sbox)
164
+
165
+ assert len(set(fixed)) == 256
166
+ assert all(0 <= v < 256 for v in fixed)
167
+
168
+
169
+ class TestNTRUPermutation:
170
+ """Test NTRU permutation generation"""
171
+
172
+ def test_permutation_correct_size(self):
173
+ """Test permutation has correct size"""
174
+ key = secrets.token_bytes(32)
175
+ perm = generate_ntru_permutation(key, 0)
176
+
177
+ assert len(perm) == NTRU_N
178
+
179
+ def test_permutation_is_valid(self):
180
+ """Test permutation contains all indices"""
181
+ key = secrets.token_bytes(32)
182
+ perm = generate_ntru_permutation(key, 0)
183
+
184
+ assert set(perm) == set(range(NTRU_N))
185
+
186
+ def test_permutation_deterministic(self):
187
+ """Test permutation generation is deterministic"""
188
+ key = secrets.token_bytes(32)
189
+
190
+ perm1 = generate_ntru_permutation(key, 0)
191
+ perm2 = generate_ntru_permutation(key, 0)
192
+
193
+ assert perm1 == perm2
194
+
195
+ def test_different_rounds_produce_different_permutations(self):
196
+ """Test different rounds produce different permutations"""
197
+ key = secrets.token_bytes(32)
198
+
199
+ perm1 = generate_ntru_permutation(key, 0)
200
+ perm2 = generate_ntru_permutation(key, 1)
201
+
202
+ assert perm1 != perm2
203
+
204
+
205
+ class TestHKDF:
206
+ """Test HKDF key derivation"""
207
+
208
+ def test_hkdf_correct_length(self):
209
+ """Test HKDF produces correct length"""
210
+ key = secrets.token_bytes(32)
211
+ derived = hkdf_sha256(key, 64)
212
+
213
+ assert len(derived) == 64
214
+
215
+ def test_hkdf_deterministic(self):
216
+ """Test HKDF is deterministic"""
217
+ key = secrets.token_bytes(32)
218
+
219
+ derived1 = hkdf_sha256(key, 64)
220
+ derived2 = hkdf_sha256(key, 64)
221
+
222
+ assert derived1 == derived2
223
+
224
+ def test_hkdf_different_info_produces_different_output(self):
225
+ """Test different info strings produce different outputs"""
226
+ key = secrets.token_bytes(32)
227
+
228
+ derived1 = hkdf_sha256(key, 64, b"info1")
229
+ derived2 = hkdf_sha256(key, 64, b"info2")
230
+
231
+ assert derived1 != derived2
232
+
233
+ def test_hkdf_different_keys_produce_different_output(self):
234
+ """Test different keys produce different outputs"""
235
+ key1 = b'A' * 32
236
+ key2 = b'B' * 32
237
+
238
+ derived1 = hkdf_sha256(key1, 64)
239
+ derived2 = hkdf_sha256(key2, 64)
240
+
241
+ assert derived1 != derived2
File without changes