|
7 | 7 | import random
|
8 | 8 | import unittest
|
9 | 9 |
|
10 |
| -from .key import fe, SECP256K1, SECP256K1_G, SECP256K1_ORDER |
| 10 | +from .key import fe, ECPubKey, SECP256K1, SECP256K1_G, SECP256K1_ORDER |
11 | 11 |
|
12 | 12 | C1 = fe(-3).sqrt()
|
13 | 13 | C2 = (C1 - fe(1)) / fe(2)
|
@@ -141,6 +141,61 @@ def reverse_map(x, y, i):
|
141 | 141 | [(fe(0x3498662504b73c7c8cecb6c33cd493bdfc190e0f87d913d7ff9ad42e222bfe95), fe(0x245b3a61b8d46997f14f2fea2874899691eb32542b9907d65eb9d21d42454021)), [fe(0x7f556282c3dd9d263390d6bbddada698ab8fd7c7d1a06498f42b30437c8361ad), None , None , None ]]
|
142 | 142 | ]
|
143 | 143 |
|
| 144 | +def encode(P): |
| 145 | + while True: |
| 146 | + u = fe(random.randrange(1, SECP256K1_ORDER)) |
| 147 | + ge = forward_map(u) |
| 148 | + # convert ge to jacobian form for EC operations |
| 149 | + ge = (ge[0].val, ge[1].val, 1) |
| 150 | + T = SECP256K1.negate(ge) |
| 151 | + Q = SECP256K1.add(T, SECP256K1.affine(P)) |
| 152 | + if SECP256K1.is_infinity(Q): |
| 153 | + Q = T |
| 154 | + j = random.randrange(4) |
| 155 | + Q = SECP256K1.affine(Q) |
| 156 | + v = reverse_map(fe(Q[0]), fe(Q[1]), j) |
| 157 | + if v is not None: |
| 158 | + return u, v |
| 159 | + |
| 160 | +def decode(u, v): |
| 161 | + ge1 = forward_map(u) |
| 162 | + ge2 = forward_map(v) |
| 163 | + # convert ge1 and ge2 to jacobian form for EC operations |
| 164 | + T = ge1[0].val, ge1[1].val, 1 |
| 165 | + S = ge2[0].val, ge2[1].val, 1 |
| 166 | + P = SECP256K1.add(T, S) |
| 167 | + if SECP256K1.is_infinity(P): |
| 168 | + P = T |
| 169 | + P = SECP256K1.affine(P) |
| 170 | + return fe(P[0]), fe(P[1]) |
| 171 | + |
| 172 | +def ellsq_encode(pubkey): |
| 173 | + """ |
| 174 | + generates elligator squared encoding of pubkey |
| 175 | + Parameters: |
| 176 | + pubkey : ECPubKey object |
| 177 | + Returns: 64 bytes encoding |
| 178 | + """ |
| 179 | + ge = pubkey.get_group_element() |
| 180 | + u, v = encode((ge[0].val, ge[1].val, 1)) |
| 181 | + return u.to_bytes() + v.to_bytes() |
| 182 | + |
| 183 | +def ellsq_decode(enc): |
| 184 | + """ |
| 185 | + decodes elligator squared encoding to obtain pubkey |
| 186 | + Parameters: |
| 187 | + enc : 64 bytes encoding |
| 188 | + Returns: ECPubKey object |
| 189 | + """ |
| 190 | + x, y = decode(fe.from_bytes(enc[:32]), fe.from_bytes(enc[32:])) |
| 191 | + if y.val % 2 == 0: |
| 192 | + compressed_sec = b'\x02' + x.val.to_bytes(32, 'big') |
| 193 | + else: |
| 194 | + compressed_sec = b'\x03' + x.val.to_bytes(32, 'big') |
| 195 | + pubkey = ECPubKey() |
| 196 | + pubkey.set(compressed_sec) |
| 197 | + return pubkey |
| 198 | + |
144 | 199 | class TestFrameworkEllsq(unittest.TestCase):
|
145 | 200 | def test_fe_to_ge_to_fe(self):
|
146 | 201 | for i in range(100):
|
|
0 commit comments