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 +10 -0
- uhc/core/__init__.py +3 -0
- uhc/core/polynomial_hash.py +240 -0
- uhc-0.1.0.dist-info/METADATA +75 -0
- uhc-0.1.0.dist-info/RECORD +8 -0
- uhc-0.1.0.dist-info/WHEEL +5 -0
- uhc-0.1.0.dist-info/licenses/LICENSE +21 -0
- uhc-0.1.0.dist-info/top_level.txt +1 -0
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,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,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
|