uhc 0.1.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.
uhc/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ UHC — Unified Hash-Compression Engine
3
+
4
+ Compressed-domain hashing over LZ77 streams.
5
+ Computes polynomial hashes of uncompressed data directly from
6
+ compressed token representations without decompression.
7
+ """
8
+
9
+ __version__ = "0.1.0"
10
+ __author__ = "UHC Contributors"
uhc/core/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """
2
+ UHC Core — algebraic primitives for compressed-domain hashing.
3
+ """
@@ -0,0 +1,240 @@
1
+ """
2
+ Polynomial hash over Z/pZ with Mersenne prime arithmetic.
3
+
4
+ Implements Definitions 1-3, Lemmas 1-2, 13-14, Theorems 1-3, 5
5
+ from the compressed-domain hashing framework.
6
+
7
+ All arithmetic is performed modulo a Mersenne prime p = 2^61 - 1
8
+ using bit-shift reduction (Lemma 14) to avoid expensive division.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ # ---------------------------------------------------------------------------
14
+ # Constants
15
+ # ---------------------------------------------------------------------------
16
+
17
+ MERSENNE_61: int = (1 << 61) - 1 # 2^61 - 1
18
+
19
+
20
+ # ---------------------------------------------------------------------------
21
+ # Mersenne prime arithmetic (Lemma 14)
22
+ # ---------------------------------------------------------------------------
23
+
24
+ def mersenne_mod(a: int, p: int = MERSENNE_61) -> int:
25
+ """
26
+ Reduce a non-negative integer a modulo a Mersenne prime p = 2^k - 1.
27
+
28
+ Uses the identity: a mod (2^k - 1) = (a >> k) + (a & ((1 << k) - 1))
29
+ with at most one conditional subtraction.
30
+
31
+ Proof (Lemma 14): Write a = q·2^k + r. Then a = q·(p+1) + r = q·p + (q+r),
32
+ so a ≡ q + r (mod p). Since q + r < 2^(k+1), at most one subtraction suffices.
33
+ """
34
+ # Determine k from p: p = 2^k - 1, so k = p.bit_length()
35
+ k = p.bit_length()
36
+ # Repeated folding for very large values
37
+ while a >= (1 << (2 * k)):
38
+ a = (a >> k) + (a & p)
39
+ # Final fold
40
+ a = (a >> k) + (a & p)
41
+ # At most one more fold needed
42
+ a = (a >> k) + (a & p)
43
+ # Conditional subtraction
44
+ if a >= p:
45
+ a -= p
46
+ return a
47
+
48
+
49
+ def mersenne_mul(a: int, b: int, p: int = MERSENNE_61) -> int:
50
+ """
51
+ Compute (a * b) mod p for Mersenne prime p.
52
+
53
+ Python's arbitrary-precision integers make this straightforward:
54
+ multiply natively, then reduce via mersenne_mod.
55
+ """
56
+ return mersenne_mod(a * b, p)
57
+
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # Geometric accumulator Φ (Definition 3, Theorem 3)
61
+ # ---------------------------------------------------------------------------
62
+
63
+ def phi(q: int, alpha: int, p: int = MERSENNE_61) -> int:
64
+ """
65
+ Compute Φ(q, α) = Σ_{i=0}^{q-1} α^i (mod p) via inverse-free
66
+ repeated doubling.
67
+
68
+ Recurrence (Theorem 3):
69
+ Φ(0, α) = 0
70
+ Φ(1, α) = 1
71
+ Φ(2k, α) = Φ(k, α) · (1 + α^k)
72
+ Φ(2k+1, α) = Φ(2k, α) · α + 1
73
+
74
+ Handles the degenerate case α ≡ 1 (mod p) correctly,
75
+ yielding Φ(q, 1) = q (mod p) (Lemma 3).
76
+
77
+ Time: O(log q) multiplications in Z/pZ.
78
+
79
+ Implementation note: We scan q's bits left-to-right (MSB to LSB).
80
+ We maintain alpha_power = α^n where n is the current accumulated
81
+ value of q built so far. At each step:
82
+ - Doubling (n → 2n): alpha_power squares (α^n → α^(2n))
83
+ - Odd step (n → n+1): alpha_power multiplies by α (α^n → α^(n+1))
84
+ This ensures the correct α^k is used in each doubling step.
85
+ """
86
+ if q == 0:
87
+ return 0
88
+ if q == 1:
89
+ return 1
90
+
91
+ bits = q.bit_length()
92
+
93
+ phi_val = 1 # Φ(1, α) = 1
94
+ alpha_power = alpha # α^1 — tracks α^(current n)
95
+
96
+ # Scan from the second-most-significant bit down to bit 0
97
+ for i in range(bits - 2, -1, -1):
98
+ # Even step: Φ(2k, α) = Φ(k, α) · (1 + α^k)
99
+ # alpha_power currently holds α^k
100
+ phi_val = mersenne_mul(phi_val, (1 + alpha_power) % p, p)
101
+ # α^k → α^(2k)
102
+ alpha_power = mersenne_mul(alpha_power, alpha_power, p)
103
+
104
+ # If current bit is 1: odd step (2k → 2k+1)
105
+ if (q >> i) & 1:
106
+ # Φ(2k+1, α) = Φ(2k, α) · α + 1
107
+ phi_val = (mersenne_mul(phi_val, alpha, p) + 1) % p
108
+ # α^(2k) → α^(2k+1)
109
+ alpha_power = mersenne_mul(alpha_power, alpha, p)
110
+
111
+ return phi_val
112
+
113
+
114
+ # ---------------------------------------------------------------------------
115
+ # Polynomial Hash (Definition 2, Theorems 1-2, 5)
116
+ # ---------------------------------------------------------------------------
117
+
118
+ class PolynomialHash:
119
+ """
120
+ Polynomial hash function over Z/pZ.
121
+
122
+ H(s) = Σ_{i=0}^{n-1} (s_i + 1) · x^(n-1-i) (mod p)
123
+
124
+ The +1 offset (Definition 2) ensures no byte maps to zero in Z/pZ,
125
+ preventing the zero-padding collision (Lemma 1).
126
+
127
+ Parameters
128
+ ----------
129
+ prime : int
130
+ A Mersenne prime. Default: 2^61 - 1.
131
+ base : int
132
+ The hash base x, chosen from {2, ..., p-1}.
133
+ """
134
+
135
+ __slots__ = ("_p", "_x", "_power_cache")
136
+
137
+ def __init__(self, prime: int = MERSENNE_61, base: int = 131) -> None:
138
+ if base < 2 or base >= prime:
139
+ raise ValueError(f"Base must be in [2, p-1], got {base}")
140
+ self._p = prime
141
+ self._x = base
142
+ self._power_cache: dict[int, int] = {0: 1, 1: base}
143
+
144
+ @property
145
+ def prime(self) -> int:
146
+ return self._p
147
+
148
+ @property
149
+ def base(self) -> int:
150
+ return self._x
151
+
152
+ def power(self, n: int) -> int:
153
+ """
154
+ Compute x^n mod p with caching.
155
+
156
+ Uses Python's built-in pow(x, n, p) which implements
157
+ binary exponentiation (Lemma 13).
158
+ """
159
+ if n in self._power_cache:
160
+ return self._power_cache[n]
161
+ result = pow(self._x, n, self._p)
162
+ self._power_cache[n] = result
163
+ return result
164
+
165
+ def hash(self, data: bytes) -> int:
166
+ """
167
+ Compute H(data) = Σ (data[i] + 1) · x^(n-1-i) (mod p).
168
+
169
+ For the empty string, returns 0 (Definition 2).
170
+
171
+ Parameters
172
+ ----------
173
+ data : bytes
174
+ The byte string to hash.
175
+
176
+ Returns
177
+ -------
178
+ int
179
+ Hash value in [0, p-1].
180
+ """
181
+ if len(data) == 0:
182
+ return 0
183
+
184
+ p = self._p
185
+ x = self._x
186
+ h = 0
187
+ for byte in data:
188
+ # h = h · x + (byte + 1)
189
+ h = mersenne_mod(h * x + byte + 1, p)
190
+ return h
191
+
192
+ def hash_concat(self, h_a: int, len_b: int, h_b: int) -> int:
193
+ """
194
+ Compute H(A ‖ B) from H(A), |B|, H(B) via Theorem 1.
195
+
196
+ H(A ‖ B) = H(A) · x^|B| + H(B) (mod p)
197
+ """
198
+ x_pow = self.power(len_b)
199
+ return mersenne_mod(h_a * x_pow + h_b, self._p)
200
+
201
+ def hash_repeat(self, h_s: int, d: int, q: int) -> int:
202
+ """
203
+ Compute H(S^q) from H(S) and |S| = d via Theorem 2.
204
+
205
+ H(S^q) = H(S) · Φ(q, x^d) (mod p)
206
+ """
207
+ x_d = self.power(d)
208
+ phi_val = phi(q, x_d, self._p)
209
+ return mersenne_mul(h_s, phi_val, self._p)
210
+
211
+ def hash_overlap(self, h_p: int, d: int, l: int, h_prefix: int) -> int:
212
+ """
213
+ Compute H(W) for overlapping back-reference via Theorem 5.
214
+
215
+ W = P^q ‖ P[0..r-1] where q = ⌊l/d⌋, r = l mod d.
216
+
217
+ H(W) = H(P) · Φ(q, x^d) · x^r + H(P[0..r-1]) (mod p)
218
+
219
+ Parameters
220
+ ----------
221
+ h_p : int
222
+ H(P), hash of the pattern of length d.
223
+ d : int
224
+ Pattern length.
225
+ l : int
226
+ Total back-reference length (d < l for overlapping).
227
+ h_prefix : int
228
+ H(P[0..r-1]) where r = l mod d. Pass 0 if r = 0.
229
+ """
230
+ q, r = divmod(l, d)
231
+ x_d = self.power(d)
232
+ x_r = self.power(r)
233
+
234
+ # H(P) · Φ(q, x^d)
235
+ phi_val = phi(q, x_d, self._p)
236
+ h_repeated = mersenne_mul(h_p, phi_val, self._p)
237
+
238
+ # · x^r + H(P[0..r-1])
239
+ result = mersenne_mod(h_repeated * x_r + h_prefix, self._p)
240
+ return result
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.4
2
+ Name: uhc
3
+ Version: 0.1.0
4
+ Summary: Unified Hash-Compression Engine: compressed-domain hashing over LZ77 streams
5
+ Author: UHC Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/uhc-framework/uhc
8
+ Project-URL: Documentation, https://github.com/uhc-framework/uhc
9
+ Project-URL: Repository, https://github.com/uhc-framework/uhc
10
+ Project-URL: Issues, https://github.com/uhc-framework/uhc/issues
11
+ Keywords: compression,hashing,lz77,deduplication,integrity,polynomial-hash,deflate,zstandard,lz4
12
+ Classifier: Development Status :: 2 - Pre-Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Topic :: System :: Archiving :: Compression
24
+ Classifier: Topic :: Security :: Cryptography
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
31
+ Provides-Extra: formats
32
+ Requires-Dist: lz4>=4.0; extra == "formats"
33
+ Requires-Dist: zstandard>=0.22; extra == "formats"
34
+ Requires-Dist: blake3>=1.0; extra == "formats"
35
+ Dynamic: license-file
36
+
37
+ # UHC — Unified Hash-Compression Engine
38
+
39
+ A Python framework for compressed-domain hashing over LZ77 streams.
40
+
41
+ UHC computes the polynomial hash of uncompressed data by operating directly on compressed token streams (DEFLATE, LZ4, Zstandard), without ever materializing the decompressed bytes.
42
+
43
+ ## Key Features
44
+
45
+ - **Compressed-domain hashing:** Compute integrity hashes without decompression
46
+ - **Hash-augmented rope:** Novel data structure with RepeatNode for O(k·log q) overlapping back-reference resolution
47
+ - **Multi-hash collision resistance:** k-wise independent polynomial hashes with configurable security levels
48
+ - **Format compatible:** DEFLATE, LZ4, Zstandard support via unified token abstraction
49
+ - **Sliding window:** O(1) memory relative to decompressed size for bounded-window formats
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install uhc
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ```python
60
+ import uhc
61
+
62
+ # Coming soon — Phase 1 implementation in progress
63
+ ```
64
+
65
+ ## Mathematical Foundation
66
+
67
+ The complete mathematical framework (24 theorems, 14 lemmas, 5 corollaries) with full proofs is available in `theory/compressed_domain_hashing_framework.md`.
68
+
69
+ ## Project Status
70
+
71
+ **Phase 1:** Algebraic core — polynomial hash, naive LZ77, compressed-domain verifier
72
+
73
+ ## License
74
+
75
+ MIT
@@ -0,0 +1,8 @@
1
+ uhc/__init__.py,sha256=T7CGom9snztDz4XD7Ibjy9IBpEIUOzLwUbHM9y2w8DA,277
2
+ uhc/core/__init__.py,sha256=6g06afsxM4SM73iY7th3zygb6BTAW2l0RKXmIKBKBOc,76
3
+ uhc/core/polynomial_hash.py,sha256=Ax7lSGkbpdQcP4QhkXP9CeJARyYbeluXAnnvNjBqz7k,7667
4
+ uhc-0.1.0.dist-info/licenses/LICENSE,sha256=R_pcSgqhj44r_nzyGqq07j_xzheZYNf7LzVTWgJU6ic,1094
5
+ uhc-0.1.0.dist-info/METADATA,sha256=db7_S4kGc3CO8N6O_zimflC6o-nTE6JTWmnaJb2vU40,2870
6
+ uhc-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
+ uhc-0.1.0.dist-info/top_level.txt,sha256=2LABdCxZjeiKXKVu51Lv4bz9kjECTKFeULJ1vAj0bdQ,4
8
+ uhc-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UHC Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ uhc