pryvx 2.4.9__tar.gz → 2.6.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pryvx
3
- Version: 2.4.9
3
+ Version: 2.6.0
4
4
  Summary: A comprehensive package for privacy-enhancing technologies
5
5
  Home-page: UNKNOWN
6
6
  Author: PryvX (Jayesh Kenaudekar)
@@ -2,4 +2,5 @@ from .psi import OPRF
2
2
  from .phe import PHE
3
3
  from .smpc import SMPC
4
4
  from .gdp import GDP
5
- from .ldp import LDP
5
+ from .ldp import LDP
6
+ from .rtphe import RTPHE
@@ -1,6 +1,7 @@
1
1
  import random
2
2
  from sympy import mod_inverse, isprime, nextprime
3
3
  import math
4
+ import hashlib
4
5
 
5
6
  def generate_prime(bits=512):
6
7
  while True:
@@ -29,6 +30,11 @@ class PHE:
29
30
  @staticmethod
30
31
  def encode(value, scale_factor=1000):
31
32
  return int(round(value * scale_factor))
33
+
34
+ @staticmethod
35
+ def hash_to_bigint(data: str) -> int:
36
+ digest = hashlib.sha256(data.encode()).hexdigest()
37
+ return int(digest, 16)
32
38
 
33
39
  @staticmethod
34
40
  def decode(value, scale_factor=1000):
@@ -0,0 +1,147 @@
1
+ import random
2
+ from sympy import mod_inverse, isprime, nextprime
3
+ import math
4
+ import hashlib
5
+ import secrets
6
+
7
+ def prove_dec(pub, c, m, r):
8
+ """
9
+ Non‑interactive PPK:
10
+ a = g^u · w^n
11
+ e = H(c || a) (Fiat–Shamir)
12
+ z = u + e·m (mod n)
13
+ w' = w · r^e (mod n)
14
+ π = (a, z, w')
15
+ """
16
+ n, g = pub ; n2 = n*n
17
+ u = secrets.randbelow(n)
18
+ w = secrets.randbelow(n)
19
+ a = (pow(g, u, n2) * pow(w, n, n2)) % n2
20
+
21
+ e = int.from_bytes(
22
+ hashlib.sha256(str(c).encode() + str(a).encode()).digest(),
23
+ 'big') % n
24
+
25
+ z = (u + e * m) % n
26
+ w_ = (w * pow(r, e, n)) % n
27
+ return a, z, w_
28
+
29
+ def verify_dec(pub, c, m, proof):
30
+ n, g = pub ; n2 = n*n
31
+ a, z, w_ = proof
32
+ e = int.from_bytes(
33
+ hashlib.sha256(str(c).encode() + str(a).encode()).digest(),
34
+ 'big') % n
35
+ left = (pow(g, z, n2) * pow(w_, n, n2)) % n2
36
+ right = (pow(c, e, n2) * a) % n2
37
+ return left == right
38
+
39
+ def generate_prime(bits=512):
40
+ while True:
41
+ p = nextprime(random.getrandbits(bits))
42
+ if isprime(p):
43
+ return p
44
+
45
+ def lcm(a, b):
46
+ return abs(a * b) // math.gcd(a, b)
47
+
48
+ class RTPHE:
49
+
50
+ @staticmethod
51
+ def keygen(bits=64):
52
+ p = generate_prime(bits)
53
+ q = generate_prime(bits)
54
+ n = p * q
55
+ lambda_n = lcm(p - 1, q - 1)
56
+ g = n + 1
57
+ mu = mod_inverse((pow(g, lambda_n, n * n) - 1) // n, n)
58
+ public_key = (n, g)
59
+ private_key = (lambda_n, mu)
60
+ return public_key, private_key
61
+
62
+ @staticmethod
63
+ def encrypt(public_key, plaintext, r=None):
64
+ n, g = public_key
65
+ if r is None:
66
+ r = random.randint(1, n - 1)
67
+ while math.gcd(r, n) != 1:
68
+ r = random.randint(1, n - 1)
69
+ n2 = n * n
70
+ c = (pow(g, plaintext, n2) * pow(r, n, n2)) % n2
71
+ return c
72
+
73
+ @staticmethod
74
+ def encrypt_with_randomness(public_key, plaintext):
75
+ r = random.randint(1, public_key[0] - 1)
76
+ while math.gcd(r, public_key[0]) != 1:
77
+ r = random.randint(1, public_key[0] - 1)
78
+ c = RTPHE.encrypt(public_key, plaintext, r)
79
+ return c, r
80
+
81
+ @staticmethod
82
+ def decrypt(public_key, private_key, ciphertext):
83
+ n, g = public_key
84
+ lambda_n, mu = private_key
85
+ n2 = n * n
86
+ x = pow(ciphertext, lambda_n, n2)
87
+ Lx = (x - 1) // n
88
+ plaintext = (Lx * mu) % n
89
+
90
+ if plaintext > n // 2:
91
+ plaintext -= n
92
+ return plaintext
93
+
94
+ @staticmethod
95
+ def homomorphic_add(c1, c2, public_key):
96
+ n2 = public_key[0] ** 2
97
+ return (c1 * c2) % n2
98
+
99
+ @staticmethod
100
+ def homomorphic_add_plaintext(ciphertext, plaintext, public_key):
101
+ n, g = public_key
102
+ n2 = n * n
103
+ c_plain = pow(g, plaintext, n2)
104
+ return (ciphertext * c_plain) % n2
105
+
106
+ @staticmethod
107
+ def homomorphic_sub(c1, c2, public_key):
108
+ n2 = public_key[0] ** 2
109
+ c2_inv = mod_inverse(c2, n2)
110
+ return (c1 * c2_inv) % n2
111
+
112
+ @staticmethod
113
+ def homomorphic_sub_plaintext(ciphertext, plaintext, public_key):
114
+ n, g = public_key
115
+ n2 = n * n
116
+ c_plain_neg = pow(g, -plaintext % n, n2)
117
+ return (ciphertext * c_plain_neg) % n2
118
+
119
+ @staticmethod
120
+ def homomorphic_scalar_mult(ciphertext, scalar, public_key):
121
+ n2 = public_key[0] ** 2
122
+ return pow(ciphertext, scalar, n2)
123
+
124
+ @staticmethod
125
+ def homomorphic_div(ciphertext, divisor, public_key):
126
+ n = public_key[0]
127
+ divisor_inv = mod_inverse(divisor, n)
128
+ return RTPHE.homomorphic_scalar_mult(ciphertext, divisor_inv, public_key)
129
+
130
+ # ========== 🔐 RANDOMNESS TRACKING HELPERS ==========
131
+
132
+ @staticmethod
133
+ def track_randomness_add(r1, r2, n):
134
+ return (r1 * r2) % n
135
+
136
+ @staticmethod
137
+ def track_randomness_sub(r1, r2, n):
138
+ return (r1 * mod_inverse(r2, n)) % n
139
+
140
+ @staticmethod
141
+ def track_randomness_scalar_mult(r, scalar, n):
142
+ return pow(r, scalar, n)
143
+
144
+ @staticmethod
145
+ def track_randomness_scalar_div(r, divisor, n):
146
+ divisor_inv = mod_inverse(divisor, n)
147
+ return pow(r, divisor_inv, n)
@@ -0,0 +1,34 @@
1
+ import random
2
+ import hashlib
3
+
4
+ def getAdditiveShares(secret, N, fieldSize):
5
+ shares = [random.randrange(fieldSize) for _ in range(N-1)]
6
+ shares.append((secret - sum(shares)) % fieldSize )
7
+ return shares
8
+
9
+ class SMPC:
10
+ def __init__(self) -> None:
11
+ self.fieldSize = 293973345475167247070445277780365744413
12
+
13
+ def encode(self, secret, scale_factor=1000):
14
+ return int(secret * scale_factor)
15
+
16
+ def decode(self, upscaled, scale_factor=1000):
17
+ return upscaled / scale_factor
18
+
19
+ def get_field_size(self):
20
+ return self.fieldSize
21
+
22
+ def get_secret_shares(self, secret, N):
23
+ shares = getAdditiveShares(secret, N, self.fieldSize)
24
+ return shares
25
+
26
+ def hash_to_bigint(self, data: str) -> int:
27
+ digest = hashlib.sha256(data.encode()).hexdigest()
28
+ return int(digest, 16)
29
+
30
+ def reconstruct(self, share):
31
+ return share % self.fieldSize
32
+
33
+ def additive_reconstruct(self, shares):
34
+ return sum(shares) % self.fieldSize
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pryvx
3
- Version: 2.4.9
3
+ Version: 2.6.0
4
4
  Summary: A comprehensive package for privacy-enhancing technologies
5
5
  Home-page: UNKNOWN
6
6
  Author: PryvX (Jayesh Kenaudekar)
@@ -11,6 +11,7 @@ pryvx/phe.py
11
11
  pryvx/pryvx_pb2.py
12
12
  pryvx/pryvx_pb2_grpc.py
13
13
  pryvx/psi.py
14
+ pryvx/rtphe.py
14
15
  pryvx/smpc.py
15
16
  pryvx.egg-info/PKG-INFO
16
17
  pryvx.egg-info/SOURCES.txt
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- VERSION = '2.4.9'
3
+ VERSION = '2.6.0'
4
4
 
5
5
 
6
6
  # Setting up
pryvx-2.4.9/pryvx/smpc.py DELETED
@@ -1,59 +0,0 @@
1
- import random
2
-
3
- def getAdditiveShares(secret, N, fieldSize):
4
- shares = [random.randrange(fieldSize) for i in range(N-1)]
5
- shares.append((secret - sum(shares)) % fieldSize )
6
- return shares
7
-
8
- def reconstructSecret(shares, fieldSize):
9
- return sum(shares) % fieldSize
10
-
11
-
12
- class SMPC:
13
- def __init__(self) -> None:
14
- self.BASE = 10
15
- self.PRECISION_INTEGRAL = 8
16
- self.PRECISION_FRACTIONAL = 8
17
- self.fieldSize = 293973345475167247070445277780365744413
18
-
19
- self.PRECISION = self.PRECISION_INTEGRAL + self.PRECISION_FRACTIONAL
20
- assert(self.fieldSize > self.BASE**self.PRECISION)
21
-
22
- def encode(self, rational):
23
- upscaled = int(rational * self.BASE**self.PRECISION_FRACTIONAL)
24
- field_element = upscaled % self.fieldSize
25
- return field_element
26
-
27
- def decode(self, field_element):
28
- upscaled = field_element if field_element <= self.fieldSize/2 else field_element - self.fieldSize
29
- rational = upscaled / self.BASE**self.PRECISION_FRACTIONAL
30
- return rational
31
-
32
- def get_secret_shares(self, m, N):
33
- N = N + 1
34
- shares = getAdditiveShares(self.encode(m), N, self.fieldSize)
35
- return shares
36
-
37
- def addition(self, shares_list):
38
- aggregate_shares = [sum(x) % self.fieldSize for x in shares_list]
39
- return self.decode(reconstructSecret(aggregate_shares, self.fieldSize))
40
-
41
- def multiplication(self):
42
- pass
43
-
44
- def difference(self, shares_a, shares_b):
45
- difference_shares = [(a - b) % self.fieldSize for a, b in zip(shares_a, shares_b)]
46
- return self.decode(reconstructSecret(difference_shares, self.fieldSize))
47
-
48
- def compare(self, shares_a, shares_b):
49
- difference_shares = [(a - b) % self.fieldSize for a, b in zip(shares_a, shares_b)]
50
- reconstructed_difference = self.decode(reconstructSecret(difference_shares, self.fieldSize))
51
-
52
- if reconstructed_difference == 0:
53
- comparison_result = "a is equal to b"
54
- elif reconstructed_difference > 0:
55
- comparison_result = "a is greater than b"
56
- else:
57
- comparison_result = "a is less than b"
58
-
59
- return comparison_result
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes