mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-30 18:35:54 +02:00
[test] Move test framework crypto functions to crypto/
This commit is contained in:
163
test/functional/test_framework/crypto/ellswift.py
Normal file
163
test/functional/test_framework/crypto/ellswift.py
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2022 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test-only Elligator Swift implementation
|
||||
|
||||
WARNING: This code is slow and uses bad randomness.
|
||||
Do not use for anything but tests."""
|
||||
|
||||
import csv
|
||||
import os
|
||||
import random
|
||||
import unittest
|
||||
|
||||
from test_framework.crypto.secp256k1 import FE, G, GE
|
||||
|
||||
# Precomputed constant square root of -3 (mod p).
|
||||
MINUS_3_SQRT = FE(-3).sqrt()
|
||||
|
||||
def xswiftec(u, t):
|
||||
"""Decode field elements (u, t) to an X coordinate on the curve."""
|
||||
if u == 0:
|
||||
u = FE(1)
|
||||
if t == 0:
|
||||
t = FE(1)
|
||||
if u**3 + t**2 + 7 == 0:
|
||||
t = 2 * t
|
||||
X = (u**3 + 7 - t**2) / (2 * t)
|
||||
Y = (X + t) / (MINUS_3_SQRT * u)
|
||||
for x in (u + 4 * Y**2, (-X / Y - u) / 2, (X / Y - u) / 2):
|
||||
if GE.is_valid_x(x):
|
||||
return x
|
||||
assert False
|
||||
|
||||
def xswiftec_inv(x, u, case):
|
||||
"""Given x and u, find t such that xswiftec(u, t) = x, or return None.
|
||||
|
||||
Case selects which of the up to 8 results to return."""
|
||||
|
||||
if case & 2 == 0:
|
||||
if GE.is_valid_x(-x - u):
|
||||
return None
|
||||
v = x
|
||||
s = -(u**3 + 7) / (u**2 + u*v + v**2)
|
||||
else:
|
||||
s = x - u
|
||||
if s == 0:
|
||||
return None
|
||||
r = (-s * (4 * (u**3 + 7) + 3 * s * u**2)).sqrt()
|
||||
if r is None:
|
||||
return None
|
||||
if case & 1 and r == 0:
|
||||
return None
|
||||
v = (-u + r / s) / 2
|
||||
w = s.sqrt()
|
||||
if w is None:
|
||||
return None
|
||||
if case & 5 == 0:
|
||||
return -w * (u * (1 - MINUS_3_SQRT) / 2 + v)
|
||||
if case & 5 == 1:
|
||||
return w * (u * (1 + MINUS_3_SQRT) / 2 + v)
|
||||
if case & 5 == 4:
|
||||
return w * (u * (1 - MINUS_3_SQRT) / 2 + v)
|
||||
if case & 5 == 5:
|
||||
return -w * (u * (1 + MINUS_3_SQRT) / 2 + v)
|
||||
|
||||
def xelligatorswift(x):
|
||||
"""Given a field element X on the curve, find (u, t) that encode them."""
|
||||
assert GE.is_valid_x(x)
|
||||
while True:
|
||||
u = FE(random.randrange(1, FE.SIZE))
|
||||
case = random.randrange(0, 8)
|
||||
t = xswiftec_inv(x, u, case)
|
||||
if t is not None:
|
||||
return u, t
|
||||
|
||||
def ellswift_create():
|
||||
"""Generate a (privkey, ellswift_pubkey) pair."""
|
||||
priv = random.randrange(1, GE.ORDER)
|
||||
u, t = xelligatorswift((priv * G).x)
|
||||
return priv.to_bytes(32, 'big'), u.to_bytes() + t.to_bytes()
|
||||
|
||||
def ellswift_ecdh_xonly(pubkey_theirs, privkey):
|
||||
"""Compute X coordinate of shared ECDH point between ellswift pubkey and privkey."""
|
||||
u = FE(int.from_bytes(pubkey_theirs[:32], 'big'))
|
||||
t = FE(int.from_bytes(pubkey_theirs[32:], 'big'))
|
||||
d = int.from_bytes(privkey, 'big')
|
||||
return (d * GE.lift_x(xswiftec(u, t))).x.to_bytes()
|
||||
|
||||
|
||||
class TestFrameworkEllSwift(unittest.TestCase):
|
||||
def test_xswiftec(self):
|
||||
"""Verify that xswiftec maps all inputs to the curve."""
|
||||
for _ in range(32):
|
||||
u = FE(random.randrange(0, FE.SIZE))
|
||||
t = FE(random.randrange(0, FE.SIZE))
|
||||
x = xswiftec(u, t)
|
||||
self.assertTrue(GE.is_valid_x(x))
|
||||
|
||||
# Check that inputs which are considered undefined in the original
|
||||
# SwiftEC paper can also be decoded successfully (by remapping)
|
||||
undefined_inputs = [
|
||||
(FE(0), FE(23)), # u = 0
|
||||
(FE(42), FE(0)), # t = 0
|
||||
(FE(5), FE(-132).sqrt()), # u^3 + t^2 + 7 = 0
|
||||
]
|
||||
assert undefined_inputs[-1][0]**3 + undefined_inputs[-1][1]**2 + 7 == 0
|
||||
for u, t in undefined_inputs:
|
||||
x = xswiftec(u, t)
|
||||
self.assertTrue(GE.is_valid_x(x))
|
||||
|
||||
def test_elligator_roundtrip(self):
|
||||
"""Verify that encoding using xelligatorswift decodes back using xswiftec."""
|
||||
for _ in range(32):
|
||||
while True:
|
||||
# Loop until we find a valid X coordinate on the curve.
|
||||
x = FE(random.randrange(1, FE.SIZE))
|
||||
if GE.is_valid_x(x):
|
||||
break
|
||||
# Encoding it to (u, t), decode it back, and compare.
|
||||
u, t = xelligatorswift(x)
|
||||
x2 = xswiftec(u, t)
|
||||
self.assertEqual(x2, x)
|
||||
|
||||
def test_ellswift_ecdh_xonly(self):
|
||||
"""Verify that shared secret computed by ellswift_ecdh_xonly match."""
|
||||
for _ in range(32):
|
||||
privkey1, encoding1 = ellswift_create()
|
||||
privkey2, encoding2 = ellswift_create()
|
||||
shared_secret1 = ellswift_ecdh_xonly(encoding1, privkey2)
|
||||
shared_secret2 = ellswift_ecdh_xonly(encoding2, privkey1)
|
||||
self.assertEqual(shared_secret1, shared_secret2)
|
||||
|
||||
def test_elligator_encode_testvectors(self):
|
||||
"""Implement the BIP324 test vectors for ellswift encoding (read from xswiftec_inv_test_vectors.csv)."""
|
||||
vectors_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'xswiftec_inv_test_vectors.csv')
|
||||
with open(vectors_file, newline='', encoding='utf8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
u = FE.from_bytes(bytes.fromhex(row['u']))
|
||||
x = FE.from_bytes(bytes.fromhex(row['x']))
|
||||
for case in range(8):
|
||||
ret = xswiftec_inv(x, u, case)
|
||||
if ret is None:
|
||||
self.assertEqual(row[f"case{case}_t"], "")
|
||||
else:
|
||||
self.assertEqual(row[f"case{case}_t"], ret.to_bytes().hex())
|
||||
self.assertEqual(xswiftec(u, ret), x)
|
||||
|
||||
def test_elligator_decode_testvectors(self):
|
||||
"""Implement the BIP324 test vectors for ellswift decoding (read from ellswift_decode_test_vectors.csv)."""
|
||||
vectors_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ellswift_decode_test_vectors.csv')
|
||||
with open(vectors_file, newline='', encoding='utf8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
encoding = bytes.fromhex(row['ellswift'])
|
||||
assert len(encoding) == 64
|
||||
expected_x = FE(int(row['x'], 16))
|
||||
u = FE(int.from_bytes(encoding[:32], 'big'))
|
||||
t = FE(int.from_bytes(encoding[32:], 'big'))
|
||||
x = xswiftec(u, t)
|
||||
self.assertEqual(x, expected_x)
|
||||
self.assertTrue(GE.is_valid_x(x))
|
||||
@@ -0,0 +1,77 @@
|
||||
ellswift,x,comment
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2)
|
||||
000000000000000000000000000000000000000000000000000000000000000001d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771,b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c,u%p=0;valid_x(x1)
|
||||
000000000000000000000000000000000000000000000000000000000000000082277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f,f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
00000000000000000000000000000000000000000000000000000000000000008421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0,9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0,u%p=0;valid_x(x2)
|
||||
0000000000000000000000000000000000000000000000000000000000000000bde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b,u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3)
|
||||
0000000000000000000000000000000000000000000000000000000000000000d19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42,70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff,u%p=0;valid_x(x3)
|
||||
0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);t>=p
|
||||
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5,50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d,1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e,u%p=0;valid_x(x2);t>=p
|
||||
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7,12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e,u%p=0;valid_x(x1);t>=p
|
||||
0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9,7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783,u%p=0;valid_x(x3);t>=p
|
||||
0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f8530000000000000000000000000000000000000000000000000000000000000000,532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688,t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
0a2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f853fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,532167c11200b08c0e84a354e74dcc40f8b25f4fe686e30869526366278a0688,t%p=0;(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646,74e880b3ffd18fe3cddf7902522551ddf97fa4a35a3cfda8197f947081a57b8f,valid_x(x3)
|
||||
0ffde9ca81d751e9cdaffc1a50779245320b28996dbaf32f822f20117c22fbd6ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896,377b643fce2271f64e5c8101566107c1be4980745091783804f654781ac9217c,valid_x(x2);t>=p
|
||||
123658444f32be8f02ea2034afa7ef4bbe8adc918ceb49b12773b625f490b368ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dc5fe11,ed16d65cf3a9538fcb2c139f1ecbc143ee14827120cbc2659e667256800b8142,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
146f92464d15d36e35382bd3ca5b0f976c95cb08acdcf2d5b3570617990839d7ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3145e93b,0d5cd840427f941f65193079ab8e2e83024ef2ee7ca558d88879ffd879fb6657,(u'^3+t'^2+7)%p=0;valid_x(x3);t>=p
|
||||
15fdf5cf09c90759add2272d574d2bb5fe1429f9f3c14c65e3194bf61b82aa73ffffffffffffffffffffffffffffffffffffffffffffffffffffffff04cfd906,16d0e43946aec93f62d57eb8cde68951af136cf4b307938dd1447411e07bffe1,(u'^3+t'^2+7)%p=0;valid_x(x2);t>=p
|
||||
1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d50000000000000000000000000000000000000000000000000000000000000000,025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c,t%p=0;valid_x(x2)
|
||||
1f67edf779a8a649d6def60035f2fa22d022dd359079a1a144073d84f19b92d5fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,025661f9aba9d15c3118456bbe980e3e1b8ba2e047c737a4eb48a040bb566f6c,t%p=0;valid_x(x2);t>=p
|
||||
1fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff507fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,98bec3b2a351fa96cfd191c1778351931b9e9ba9ad1149f6d9eadca80981b801,t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
4056a34a210eec7892e8820675c860099f857b26aad85470ee6d3cf1304a9dcf375e70374271f20b13c9986ed7d3c17799698cfc435dbed3a9f34b38c823c2b4,868aac2003b29dbcad1a3e803855e078a89d16543ac64392d122417298cec76e,(u'^3-t'^2+7)%p=0;valid_x(x3)
|
||||
4197ec3723c654cfdd32ab075506648b2ff5070362d01a4fff14b336b78f963fffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3ab1e95,ba5a6314502a8952b8f456e085928105f665377a8ce27726a5b0eb7ec1ac0286,(u'^3+t'^2+7)%p=0;valid_x(x1);t>=p
|
||||
47eb3e208fedcdf8234c9421e9cd9a7ae873bfbdbc393723d1ba1e1e6a8e6b24ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7cd12cb1,d192d52007e541c9807006ed0468df77fd214af0a795fe119359666fdcf08f7c,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
5eb9696a2336fe2c3c666b02c755db4c0cfd62825c7b589a7b7bb442e141c1d693413f0052d49e64abec6d5831d66c43612830a17df1fe4383db896468100221,ef6e1da6d6c7627e80f7a7234cb08a022c1ee1cf29e4d0f9642ae924cef9eb38,(u'^3+t'^2+7)%p=0;valid_x(x1)
|
||||
7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0e0000000000000000000000000000000000000000000000000000000000000000,50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff,t%p=0;valid_x(x1)
|
||||
7bf96b7b6da15d3476a2b195934b690a3a3de3e8ab8474856863b0de3af90b0efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,50851dfc9f418c314a437295b24feeea27af3d0cd2308348fda6e21c463e46ff,t%p=0;valid_x(x1);t>=p
|
||||
851b1ca94549371c4f1f7187321d39bf51c6b7fb61f7cbf027c9da62021b7a65fc54c96837fb22b362eda63ec52ec83d81bedd160c11b22d965d9f4a6d64d251,3e731051e12d33237eb324f2aa5b16bb868eb49a1aa1fadc19b6e8761b5a5f7b,(u'^3+t'^2+7)%p=0;valid_x(x2)
|
||||
943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f91250000000000000000000000000000000000000000000000000000000000000000,311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
943c2f775108b737fe65a9531e19f2fc2a197f5603e3a2881d1d83e4008f9125fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,311c61f0ab2f32b7b1f0223fa72f0a78752b8146e46107f8876dd9c4f92b2942,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
a0f18492183e61e8063e573606591421b06bc3513631578a73a39c1c3306239f2f32904f0d2a33ecca8a5451705bb537d3bf44e071226025cdbfd249fe0f7ad6,97a09cf1a2eae7c494df3c6f8a9445bfb8c09d60832f9b0b9d5eabe25fbd14b9,valid_x(x1)
|
||||
a1ed0a0bd79d8a23cfe4ec5fef5ba5cccfd844e4ff5cb4b0f2e71627341f1c5b17c499249e0ac08d5d11ea1c2c8ca7001616559a7994eadec9ca10fb4b8516dc,65a89640744192cdac64b2d21ddf989cdac7500725b645bef8e2200ae39691f2,valid_x(x2)
|
||||
ba94594a432721aa3580b84c161d0d134bc354b690404d7cd4ec57c16d3fbe98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffea507dd7,5e0d76564aae92cb347e01a62afd389a9aa401c76c8dd227543dc9cd0efe685a,valid_x(x1);t>=p
|
||||
bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a,2d97f96cac882dfe73dc44db6ce0f1d31d6241358dd5d74eb3d3b50003d24c2b,valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
bcaf7219f2f6fbf55fe5e062dce0e48c18f68103f10b8198e974c184750e1be3ffffffffffffffffffffffffffffffffffffffffffffffffffffffff6507d09a,e7008afe6e8cbd5055df120bd748757c686dadb41cce75e4addcc5e02ec02b44,valid_x(x3);valid_x(x2);valid_x(x1);t>=p
|
||||
c5981bae27fd84401c72a155e5707fbb811b2b620645d1028ea270cbe0ee225d4b62aa4dca6506c1acdbecc0552569b4b21436a5692e25d90d3bc2eb7ce24078,948b40e7181713bc018ec1702d3d054d15746c59a7020730dd13ecf985a010d7,(u'^3+t'^2+7)%p=0;valid_x(x3)
|
||||
c894ce48bfec433014b931a6ad4226d7dbd8eaa7b6e3faa8d0ef94052bcf8cff336eeb3919e2b4efb746c7f71bbca7e9383230fbbc48ffafe77e8bcc69542471,f1c91acdc2525330f9b53158434a4d43a1c547cff29f15506f5da4eb4fe8fa5a,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000000,872d81ed8831d9998b67cb7105243edbf86c10edfebb786c110b02d07b2e67cd,t%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
d917b786dac35670c330c9c5ae5971dfb495c8ae523ed97ee2420117b171f41effffffffffffffffffffffffffffffffffffffffffffffffffffffff2001f6f6,e45b71e110b831f2bdad8651994526e58393fde4328b1ec04d59897142584691,valid_x(x3);t>=p
|
||||
e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb4260000000000000000000000000000000000000000000000000000000000000000,66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5,t%p=0;valid_x(x3)
|
||||
e28bd8f5929b467eb70e04332374ffb7e7180218ad16eaa46b7161aa679eb426fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,66b8c980a75c72e598d383a35a62879f844242ad1e73ff12edaa59f4e58632b5,t%p=0;valid_x(x3);t>=p
|
||||
e7ee5814c1706bf8a89396a9b032bc014c2cac9c121127dbf6c99278f8bb53d1dfd04dbcda8e352466b6fcd5f2dea3e17d5e133115886eda20db8a12b54de71b,e842c6e3529b234270a5e97744edc34a04d7ba94e44b6d2523c9cf0195730a50,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1)
|
||||
f292e46825f9225ad23dc057c1d91c4f57fcb1386f29ef10481cb1d22518593fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7011c989,3cea2c53b8b0170166ac7da67194694adacc84d56389225e330134dab85a4d55,(u'^3-t'^2+7)%p=0;valid_x(x3);t>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f01d3475bf7655b0fb2d852921035b2ef607f49069b97454e6795251062741771,b5da00b73cd6560520e7c364086e7cd23a34bf60d0e707be9fc34d4cd5fdfa2c,u%p=0;valid_x(x1);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9fffffd6b,u%p=0;(u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f82277c4a71f9d22e66ece523f8fa08741a7c0912c66a69ce68514bfd3515b49f,f482f2e241753ad0fb89150d8491dc1e34ff0b8acfbb442cfe999e2e5e6fd1d2,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f8421cc930e77c9f514b6915c3dbe2a94c6d8f690b5b739864ba6789fb8a55dd0,9f59c40275f5085a006f05dae77eb98c6fd0db1ab4a72ac47eae90a4fc9e57e0,u%p=0;valid_x(x2);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fd19c182d2759cd99824228d94799f8c6557c38a1c0d6779b9d4b729c6f1ccc42,70720db7e238d04121f5b1afd8cc5ad9d18944c6bdc94881f502b7a3af3aecff,u%p=0;valid_x(x3);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,edd1fd3e327ce90cc7a3542614289aee9682003e9cf7dcc9cf2ca9743be5aa0c,u%p=0;t%p=0;valid_x(x2);u>=p;t>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff2664bbd5,50873db31badcc71890e4f67753a65757f97aaa7dd5f1e82b753ace32219064b,u%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7028de7d,1eea9cc59cfcf2fa151ac6c274eea4110feb4f7b68c5965732e9992e976ef68e,u%p=0;valid_x(x2);u>=p;t>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffcbcfb7e7,12303941aedc208880735b1f1795c8e55be520ea93e103357b5d2adb7ed59b8e,u%p=0;valid_x(x1);u>=p;t>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3113ad9,7eed6b70e7b0767c7d7feac04e57aa2a12fef5e0f48f878fcbb88b3b6b5e0783,u%p=0;valid_x(x3);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a70000000000000000000000000000000000000000000000000000000000000000,649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb,t%p=0;valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff13cea4a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,649984435b62b4a25d40c6133e8d9ab8c53d4b059ee8a154a3be0fcf4e892edb,t%p=0;valid_x(x1);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff15028c590063f64d5a7f1c14915cd61eac886ab295bebd91992504cf77edb028bdd6267f,3fde5713f8282eead7d39d4201f44a7c85a5ac8a0681f35e54085c6b69543374,(u'^3+t'^2+7)%p=0;valid_x(x2);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de860000000000000000000000000000000000000000000000000000000000000000,3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2715de86fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,3524f77fa3a6eb4389c3cb5d27f1f91462086429cd6c0cb0df43ea8f1e7b3fb4,t%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2c2c5709e7156c417717f2feab147141ec3da19fb759575cc6e37b2ea5ac9309f26f0f66,d2469ab3e04acbb21c65a1809f39caafe7a77c13d10f9dd38f391c01dc499c52,(u'^3-t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3a08cc1efffffffffffffffffffffffffffffffffffffffffffffffffffffffff760e9f0,38e2a5ce6a93e795e16d2c398bc99f0369202ce21e8f09d56777b40fc512bccc,valid_x(x3);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e91257d932016cbf69c4471bd1f656c6a107f1973de4af7086db897277060e25677f19a,864b3dc902c376709c10a93ad4bbe29fce0012f3dc8672c6286bba28d7d6d6fc,valid_x(x3);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff795d6c1c322cadf599dbb86481522b3cc55f15a67932db2afa0111d9ed6981bcd124bf44,766dfe4a700d9bee288b903ad58870e3d4fe2f0ef780bcac5c823f320d9a9bef,(u'^3+t'^2+7)%p=0;valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e426f0392389078c12b1a89e9542f0593bc96b6bfde8224f8654ef5d5cda935a3582194,faec7bc1987b63233fbc5f956edbf37d54404e7461c58ab8631bc68e451a0478,valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff91192139ffffffffffffffffffffffffffffffffffffffffffffffffffffffff45f0f1eb,ec29a50bae138dbf7d8e24825006bb5fc1a2cc1243ba335bc6116fb9e498ec1f,valid_x(x2);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff98eb9ab76e84499c483b3bf06214abfe065dddf43b8601de596d63b9e45a166a580541fe,1e0ff2dee9b09b136292a9e910f0d6ac3e552a644bba39e64e9dd3e3bbd3d4d4,(u'^3-t'^2+7)%p=0;valid_x(x3);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2c74d99efceaa550f1ad1c0f43f46e7ff1ee3bd0162b7bf55f2965da9c3450646,8b7dd5c3edba9ee97b70eff438f22dca9849c8254a2f3345a0a572ffeaae0928,valid_x(x2);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b77b7f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffff156ca896,0881950c8f51d6b9a6387465d5f12609ef1bb25412a08a74cb2dfb200c74bfbf,valid_x(x3);valid_x(x2);valid_x(x1);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffa2f5cd838816c16c4fe8a1661d606fdb13cf9af04b979a2e159a09409ebc8645d58fde02,2f083207b9fd9b550063c31cd62b8746bd543bdc5bbf10e3a35563e927f440c8,(u'^3+t'^2+7)%p=0;valid_x(x3);valid_x(x2);valid_x(x1);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c00000000000000000000000000000000000000000000000000000000000000000,4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0,t%p=0;valid_x(x3);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb13f75c0fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,4f51e0be078e0cddab2742156adba7e7a148e73157072fd618cd60942b146bd0,t%p=0;valid_x(x3);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8d0000000000000000000000000000000000000000000000000000000000000000,16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2,t%p=0;valid_x(x2);u>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7bc1f8dfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,16c2ccb54352ff4bd794f6efd613c72197ab7082da5b563bdf9cb3edaafe74c2,t%p=0;valid_x(x2);u>=p;t>=p
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffef64d162750546ce42b0431361e52d4f5242d8f24f33e6b1f99b591647cbc808f462af51,d41244d11ca4f65240687759f95ca9efbab767ededb38fd18c36e18cd3b6f6a9,(u'^3+t'^2+7)%p=0;valid_x(x3);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0e5be52372dd6e894b2a326fc3605a6e8f3c69c710bf27d630dfe2004988b78eb6eab36,64bf84dd5e03670fdb24c0f5d3c2c365736f51db6c92d95010716ad2d36134c8,valid_x(x3);valid_x(x2);valid_x(x1);u>=p
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefbb982fffffffffffffffffffffffffffffffffffffffffffffffffffffffff6d6db1f,1c92ccdfcf4ac550c28db57cff0c8515cb26936c786584a70114008d6c33a34b,valid_x(x1);u>=p;t>=p
|
||||
|
110
test/functional/test_framework/crypto/muhash.py
Normal file
110
test/functional/test_framework/crypto/muhash.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) 2020 Pieter Wuille
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Native Python MuHash3072 implementation."""
|
||||
|
||||
import hashlib
|
||||
import unittest
|
||||
|
||||
def rot32(v, bits):
|
||||
"""Rotate the 32-bit value v left by bits bits."""
|
||||
bits %= 32 # Make sure the term below does not throw an exception
|
||||
return ((v << bits) & 0xffffffff) | (v >> (32 - bits))
|
||||
|
||||
def chacha20_doubleround(s):
|
||||
"""Apply a ChaCha20 double round to 16-element state array s.
|
||||
|
||||
See https://cr.yp.to/chacha/chacha-20080128.pdf and https://tools.ietf.org/html/rfc8439
|
||||
"""
|
||||
QUARTER_ROUNDS = [(0, 4, 8, 12),
|
||||
(1, 5, 9, 13),
|
||||
(2, 6, 10, 14),
|
||||
(3, 7, 11, 15),
|
||||
(0, 5, 10, 15),
|
||||
(1, 6, 11, 12),
|
||||
(2, 7, 8, 13),
|
||||
(3, 4, 9, 14)]
|
||||
|
||||
for a, b, c, d in QUARTER_ROUNDS:
|
||||
s[a] = (s[a] + s[b]) & 0xffffffff
|
||||
s[d] = rot32(s[d] ^ s[a], 16)
|
||||
s[c] = (s[c] + s[d]) & 0xffffffff
|
||||
s[b] = rot32(s[b] ^ s[c], 12)
|
||||
s[a] = (s[a] + s[b]) & 0xffffffff
|
||||
s[d] = rot32(s[d] ^ s[a], 8)
|
||||
s[c] = (s[c] + s[d]) & 0xffffffff
|
||||
s[b] = rot32(s[b] ^ s[c], 7)
|
||||
|
||||
def chacha20_32_to_384(key32):
|
||||
"""Specialized ChaCha20 implementation with 32-byte key, 0 IV, 384-byte output."""
|
||||
# See RFC 8439 section 2.3 for chacha20 parameters
|
||||
CONSTANTS = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]
|
||||
|
||||
key_bytes = [0]*8
|
||||
for i in range(8):
|
||||
key_bytes[i] = int.from_bytes(key32[(4 * i):(4 * (i+1))], 'little')
|
||||
|
||||
INITIALIZATION_VECTOR = [0] * 4
|
||||
init = CONSTANTS + key_bytes + INITIALIZATION_VECTOR
|
||||
out = bytearray()
|
||||
for counter in range(6):
|
||||
init[12] = counter
|
||||
s = init.copy()
|
||||
for _ in range(10):
|
||||
chacha20_doubleround(s)
|
||||
for i in range(16):
|
||||
out.extend(((s[i] + init[i]) & 0xffffffff).to_bytes(4, 'little'))
|
||||
return bytes(out)
|
||||
|
||||
def data_to_num3072(data):
|
||||
"""Hash a 32-byte array data to a 3072-bit number using 6 Chacha20 operations."""
|
||||
bytes384 = chacha20_32_to_384(data)
|
||||
return int.from_bytes(bytes384, 'little')
|
||||
|
||||
class MuHash3072:
|
||||
"""Class representing the MuHash3072 computation of a set.
|
||||
|
||||
See https://cseweb.ucsd.edu/~mihir/papers/inchash.pdf and https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014337.html
|
||||
"""
|
||||
|
||||
MODULUS = 2**3072 - 1103717
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize for an empty set."""
|
||||
self.numerator = 1
|
||||
self.denominator = 1
|
||||
|
||||
def insert(self, data):
|
||||
"""Insert a byte array data in the set."""
|
||||
data_hash = hashlib.sha256(data).digest()
|
||||
self.numerator = (self.numerator * data_to_num3072(data_hash)) % self.MODULUS
|
||||
|
||||
def remove(self, data):
|
||||
"""Remove a byte array from the set."""
|
||||
data_hash = hashlib.sha256(data).digest()
|
||||
self.denominator = (self.denominator * data_to_num3072(data_hash)) % self.MODULUS
|
||||
|
||||
def digest(self):
|
||||
"""Extract the final hash. Does not modify this object."""
|
||||
val = (self.numerator * pow(self.denominator, -1, self.MODULUS)) % self.MODULUS
|
||||
bytes384 = val.to_bytes(384, 'little')
|
||||
return hashlib.sha256(bytes384).digest()
|
||||
|
||||
class TestFrameworkMuhash(unittest.TestCase):
|
||||
def test_muhash(self):
|
||||
muhash = MuHash3072()
|
||||
muhash.insert(b'\x00' * 32)
|
||||
muhash.insert((b'\x01' + b'\x00' * 31))
|
||||
muhash.remove((b'\x02' + b'\x00' * 31))
|
||||
finalized = muhash.digest()
|
||||
# This mirrors the result in the C++ MuHash3072 unit test
|
||||
self.assertEqual(finalized[::-1].hex(), "10d312b100cbd32ada024a6646e40d3482fcff103668d2625f10002a607d5863")
|
||||
|
||||
def test_chacha20(self):
|
||||
def chacha_check(key, result):
|
||||
self.assertEqual(chacha20_32_to_384(key)[:64].hex(), result)
|
||||
|
||||
# Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
|
||||
# Since the nonce is hardcoded to 0 in our function we only use those vectors.
|
||||
chacha_check([0]*32, "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586")
|
||||
chacha_check([0]*31 + [1], "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963")
|
||||
130
test/functional/test_framework/crypto/ripemd160.py
Normal file
130
test/functional/test_framework/crypto/ripemd160.py
Normal file
@@ -0,0 +1,130 @@
|
||||
# Copyright (c) 2021 Pieter Wuille
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test-only pure Python RIPEMD160 implementation."""
|
||||
|
||||
import unittest
|
||||
|
||||
# Message schedule indexes for the left path.
|
||||
ML = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
||||
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
||||
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
||||
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
||||
]
|
||||
|
||||
# Message schedule indexes for the right path.
|
||||
MR = [
|
||||
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
||||
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
||||
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
||||
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
||||
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
||||
]
|
||||
|
||||
# Rotation counts for the left path.
|
||||
RL = [
|
||||
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
||||
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
||||
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
||||
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
||||
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
||||
]
|
||||
|
||||
# Rotation counts for the right path.
|
||||
RR = [
|
||||
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
||||
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
||||
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
||||
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
||||
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
||||
]
|
||||
|
||||
# K constants for the left path.
|
||||
KL = [0, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e]
|
||||
|
||||
# K constants for the right path.
|
||||
KR = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0]
|
||||
|
||||
|
||||
def fi(x, y, z, i):
|
||||
"""The f1, f2, f3, f4, and f5 functions from the specification."""
|
||||
if i == 0:
|
||||
return x ^ y ^ z
|
||||
elif i == 1:
|
||||
return (x & y) | (~x & z)
|
||||
elif i == 2:
|
||||
return (x | ~y) ^ z
|
||||
elif i == 3:
|
||||
return (x & z) | (y & ~z)
|
||||
elif i == 4:
|
||||
return x ^ (y | ~z)
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
||||
def rol(x, i):
|
||||
"""Rotate the bottom 32 bits of x left by i bits."""
|
||||
return ((x << i) | ((x & 0xffffffff) >> (32 - i))) & 0xffffffff
|
||||
|
||||
|
||||
def compress(h0, h1, h2, h3, h4, block):
|
||||
"""Compress state (h0, h1, h2, h3, h4) with block."""
|
||||
# Left path variables.
|
||||
al, bl, cl, dl, el = h0, h1, h2, h3, h4
|
||||
# Right path variables.
|
||||
ar, br, cr, dr, er = h0, h1, h2, h3, h4
|
||||
# Message variables.
|
||||
x = [int.from_bytes(block[4*i:4*(i+1)], 'little') for i in range(16)]
|
||||
|
||||
# Iterate over the 80 rounds of the compression.
|
||||
for j in range(80):
|
||||
rnd = j >> 4
|
||||
# Perform left side of the transformation.
|
||||
al = rol(al + fi(bl, cl, dl, rnd) + x[ML[j]] + KL[rnd], RL[j]) + el
|
||||
al, bl, cl, dl, el = el, al, bl, rol(cl, 10), dl
|
||||
# Perform right side of the transformation.
|
||||
ar = rol(ar + fi(br, cr, dr, 4 - rnd) + x[MR[j]] + KR[rnd], RR[j]) + er
|
||||
ar, br, cr, dr, er = er, ar, br, rol(cr, 10), dr
|
||||
|
||||
# Compose old state, left transform, and right transform into new state.
|
||||
return h1 + cl + dr, h2 + dl + er, h3 + el + ar, h4 + al + br, h0 + bl + cr
|
||||
|
||||
|
||||
def ripemd160(data):
|
||||
"""Compute the RIPEMD-160 hash of data."""
|
||||
# Initialize state.
|
||||
state = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0)
|
||||
# Process full 64-byte blocks in the input.
|
||||
for b in range(len(data) >> 6):
|
||||
state = compress(*state, data[64*b:64*(b+1)])
|
||||
# Construct final blocks (with padding and size).
|
||||
pad = b"\x80" + b"\x00" * ((119 - len(data)) & 63)
|
||||
fin = data[len(data) & ~63:] + pad + (8 * len(data)).to_bytes(8, 'little')
|
||||
# Process final blocks.
|
||||
for b in range(len(fin) >> 6):
|
||||
state = compress(*state, fin[64*b:64*(b+1)])
|
||||
# Produce output.
|
||||
return b"".join((h & 0xffffffff).to_bytes(4, 'little') for h in state)
|
||||
|
||||
|
||||
class TestFrameworkKey(unittest.TestCase):
|
||||
def test_ripemd160(self):
|
||||
"""RIPEMD-160 test vectors."""
|
||||
# See https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
||||
for msg, hexout in [
|
||||
(b"", "9c1185a5c5e9fc54612808977ee8f548b2258d31"),
|
||||
(b"a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"),
|
||||
(b"abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"),
|
||||
(b"message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"),
|
||||
(b"abcdefghijklmnopqrstuvwxyz",
|
||||
"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"),
|
||||
(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"12a053384a9c0c88e405a06c27dcf49ada62eb2b"),
|
||||
(b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"b0e20b6e3116640286ed3a87a5713079b21f5189"),
|
||||
(b"1234567890" * 8, "9b752e45573d4b39f4dbd3323cab82bf63326bfb"),
|
||||
(b"a" * 1000000, "52783243c1697bdbe16d37f97f68f08325dc1528")
|
||||
]:
|
||||
self.assertEqual(ripemd160(msg).hex(), hexout)
|
||||
346
test/functional/test_framework/crypto/secp256k1.py
Normal file
346
test/functional/test_framework/crypto/secp256k1.py
Normal file
@@ -0,0 +1,346 @@
|
||||
# Copyright (c) 2022-2023 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
"""Test-only implementation of low-level secp256k1 field and group arithmetic
|
||||
|
||||
It is designed for ease of understanding, not performance.
|
||||
|
||||
WARNING: This code is slow and trivially vulnerable to side channel attacks. Do not use for
|
||||
anything but tests.
|
||||
|
||||
Exports:
|
||||
* FE: class for secp256k1 field elements
|
||||
* GE: class for secp256k1 group elements
|
||||
* G: the secp256k1 generator point
|
||||
"""
|
||||
|
||||
|
||||
class FE:
|
||||
"""Objects of this class represent elements of the field GF(2**256 - 2**32 - 977).
|
||||
|
||||
They are represented internally in numerator / denominator form, in order to delay inversions.
|
||||
"""
|
||||
|
||||
# The size of the field (also its modulus and characteristic).
|
||||
SIZE = 2**256 - 2**32 - 977
|
||||
|
||||
def __init__(self, a=0, b=1):
|
||||
"""Initialize a field element a/b; both a and b can be ints or field elements."""
|
||||
if isinstance(a, FE):
|
||||
num = a._num
|
||||
den = a._den
|
||||
else:
|
||||
num = a % FE.SIZE
|
||||
den = 1
|
||||
if isinstance(b, FE):
|
||||
den = (den * b._num) % FE.SIZE
|
||||
num = (num * b._den) % FE.SIZE
|
||||
else:
|
||||
den = (den * b) % FE.SIZE
|
||||
assert den != 0
|
||||
if num == 0:
|
||||
den = 1
|
||||
self._num = num
|
||||
self._den = den
|
||||
|
||||
def __add__(self, a):
|
||||
"""Compute the sum of two field elements (second may be int)."""
|
||||
if isinstance(a, FE):
|
||||
return FE(self._num * a._den + self._den * a._num, self._den * a._den)
|
||||
return FE(self._num + self._den * a, self._den)
|
||||
|
||||
def __radd__(self, a):
|
||||
"""Compute the sum of an integer and a field element."""
|
||||
return FE(a) + self
|
||||
|
||||
def __sub__(self, a):
|
||||
"""Compute the difference of two field elements (second may be int)."""
|
||||
if isinstance(a, FE):
|
||||
return FE(self._num * a._den - self._den * a._num, self._den * a._den)
|
||||
return FE(self._num - self._den * a, self._den)
|
||||
|
||||
def __rsub__(self, a):
|
||||
"""Compute the difference of an integer and a field element."""
|
||||
return FE(a) - self
|
||||
|
||||
def __mul__(self, a):
|
||||
"""Compute the product of two field elements (second may be int)."""
|
||||
if isinstance(a, FE):
|
||||
return FE(self._num * a._num, self._den * a._den)
|
||||
return FE(self._num * a, self._den)
|
||||
|
||||
def __rmul__(self, a):
|
||||
"""Compute the product of an integer with a field element."""
|
||||
return FE(a) * self
|
||||
|
||||
def __truediv__(self, a):
|
||||
"""Compute the ratio of two field elements (second may be int)."""
|
||||
return FE(self, a)
|
||||
|
||||
def __pow__(self, a):
|
||||
"""Raise a field element to an integer power."""
|
||||
return FE(pow(self._num, a, FE.SIZE), pow(self._den, a, FE.SIZE))
|
||||
|
||||
def __neg__(self):
|
||||
"""Negate a field element."""
|
||||
return FE(-self._num, self._den)
|
||||
|
||||
def __int__(self):
|
||||
"""Convert a field element to an integer in range 0..p-1. The result is cached."""
|
||||
if self._den != 1:
|
||||
self._num = (self._num * pow(self._den, -1, FE.SIZE)) % FE.SIZE
|
||||
self._den = 1
|
||||
return self._num
|
||||
|
||||
def sqrt(self):
|
||||
"""Compute the square root of a field element if it exists (None otherwise).
|
||||
|
||||
Due to the fact that our modulus is of the form (p % 4) == 3, the Tonelli-Shanks
|
||||
algorithm (https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm) is simply
|
||||
raising the argument to the power (p + 1) / 4.
|
||||
|
||||
To see why: (p-1) % 2 = 0, so 2 divides the order of the multiplicative group,
|
||||
and thus only half of the non-zero field elements are squares. An element a is
|
||||
a (nonzero) square when Euler's criterion, a^((p-1)/2) = 1 (mod p), holds. We're
|
||||
looking for x such that x^2 = a (mod p). Given a^((p-1)/2) = 1, that is equivalent
|
||||
to x^2 = a^(1 + (p-1)/2) mod p. As (1 + (p-1)/2) is even, this is equivalent to
|
||||
x = a^((1 + (p-1)/2)/2) mod p, or x = a^((p+1)/4) mod p."""
|
||||
v = int(self)
|
||||
s = pow(v, (FE.SIZE + 1) // 4, FE.SIZE)
|
||||
if s**2 % FE.SIZE == v:
|
||||
return FE(s)
|
||||
return None
|
||||
|
||||
def is_square(self):
|
||||
"""Determine if this field element has a square root."""
|
||||
# A more efficient algorithm is possible here (Jacobi symbol).
|
||||
return self.sqrt() is not None
|
||||
|
||||
def is_even(self):
|
||||
"""Determine whether this field element, represented as integer in 0..p-1, is even."""
|
||||
return int(self) & 1 == 0
|
||||
|
||||
def __eq__(self, a):
|
||||
"""Check whether two field elements are equal (second may be an int)."""
|
||||
if isinstance(a, FE):
|
||||
return (self._num * a._den - self._den * a._num) % FE.SIZE == 0
|
||||
return (self._num - self._den * a) % FE.SIZE == 0
|
||||
|
||||
def to_bytes(self):
|
||||
"""Convert a field element to a 32-byte array (BE byte order)."""
|
||||
return int(self).to_bytes(32, 'big')
|
||||
|
||||
@staticmethod
|
||||
def from_bytes(b):
|
||||
"""Convert a 32-byte array to a field element (BE byte order, no overflow allowed)."""
|
||||
v = int.from_bytes(b, 'big')
|
||||
if v >= FE.SIZE:
|
||||
return None
|
||||
return FE(v)
|
||||
|
||||
def __str__(self):
|
||||
"""Convert this field element to a 64 character hex string."""
|
||||
return f"{int(self):064x}"
|
||||
|
||||
def __repr__(self):
|
||||
"""Get a string representation of this field element."""
|
||||
return f"FE(0x{int(self):x})"
|
||||
|
||||
|
||||
class GE:
|
||||
"""Objects of this class represent secp256k1 group elements (curve points or infinity)
|
||||
|
||||
Normal points on the curve have fields:
|
||||
* x: the x coordinate (a field element)
|
||||
* y: the y coordinate (a field element, satisfying y^2 = x^3 + 7)
|
||||
* infinity: False
|
||||
|
||||
The point at infinity has field:
|
||||
* infinity: True
|
||||
"""
|
||||
|
||||
# Order of the group (number of points on the curve, plus 1 for infinity)
|
||||
ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||
|
||||
# Number of valid distinct x coordinates on the curve.
|
||||
ORDER_HALF = ORDER // 2
|
||||
|
||||
def __init__(self, x=None, y=None):
|
||||
"""Initialize a group element with specified x and y coordinates, or infinity."""
|
||||
if x is None:
|
||||
# Initialize as infinity.
|
||||
assert y is None
|
||||
self.infinity = True
|
||||
else:
|
||||
# Initialize as point on the curve (and check that it is).
|
||||
fx = FE(x)
|
||||
fy = FE(y)
|
||||
assert fy**2 == fx**3 + 7
|
||||
self.infinity = False
|
||||
self.x = fx
|
||||
self.y = fy
|
||||
|
||||
def __add__(self, a):
|
||||
"""Add two group elements together."""
|
||||
# Deal with infinity: a + infinity == infinity + a == a.
|
||||
if self.infinity:
|
||||
return a
|
||||
if a.infinity:
|
||||
return self
|
||||
if self.x == a.x:
|
||||
if self.y != a.y:
|
||||
# A point added to its own negation is infinity.
|
||||
assert self.y + a.y == 0
|
||||
return GE()
|
||||
else:
|
||||
# For identical inputs, use the tangent (doubling formula).
|
||||
lam = (3 * self.x**2) / (2 * self.y)
|
||||
else:
|
||||
# For distinct inputs, use the line through both points (adding formula).
|
||||
lam = (self.y - a.y) / (self.x - a.x)
|
||||
# Determine point opposite to the intersection of that line with the curve.
|
||||
x = lam**2 - (self.x + a.x)
|
||||
y = lam * (self.x - x) - self.y
|
||||
return GE(x, y)
|
||||
|
||||
@staticmethod
|
||||
def mul(*aps):
|
||||
"""Compute a (batch) scalar group element multiplication.
|
||||
|
||||
GE.mul((a1, p1), (a2, p2), (a3, p3)) is identical to a1*p1 + a2*p2 + a3*p3,
|
||||
but more efficient."""
|
||||
# Reduce all the scalars modulo order first (so we can deal with negatives etc).
|
||||
naps = [(a % GE.ORDER, p) for a, p in aps]
|
||||
# Start with point at infinity.
|
||||
r = GE()
|
||||
# Iterate over all bit positions, from high to low.
|
||||
for i in range(255, -1, -1):
|
||||
# Double what we have so far.
|
||||
r = r + r
|
||||
# Add then add the points for which the corresponding scalar bit is set.
|
||||
for (a, p) in naps:
|
||||
if (a >> i) & 1:
|
||||
r += p
|
||||
return r
|
||||
|
||||
def __rmul__(self, a):
|
||||
"""Multiply an integer with a group element."""
|
||||
if self == G:
|
||||
return FAST_G.mul(a)
|
||||
return GE.mul((a, self))
|
||||
|
||||
def __neg__(self):
|
||||
"""Compute the negation of a group element."""
|
||||
if self.infinity:
|
||||
return self
|
||||
return GE(self.x, -self.y)
|
||||
|
||||
def to_bytes_compressed(self):
|
||||
"""Convert a non-infinite group element to 33-byte compressed encoding."""
|
||||
assert not self.infinity
|
||||
return bytes([3 - self.y.is_even()]) + self.x.to_bytes()
|
||||
|
||||
def to_bytes_uncompressed(self):
|
||||
"""Convert a non-infinite group element to 65-byte uncompressed encoding."""
|
||||
assert not self.infinity
|
||||
return b'\x04' + self.x.to_bytes() + self.y.to_bytes()
|
||||
|
||||
def to_bytes_xonly(self):
|
||||
"""Convert (the x coordinate of) a non-infinite group element to 32-byte xonly encoding."""
|
||||
assert not self.infinity
|
||||
return self.x.to_bytes()
|
||||
|
||||
@staticmethod
|
||||
def lift_x(x):
|
||||
"""Return group element with specified field element as x coordinate (and even y)."""
|
||||
y = (FE(x)**3 + 7).sqrt()
|
||||
if y is None:
|
||||
return None
|
||||
if not y.is_even():
|
||||
y = -y
|
||||
return GE(x, y)
|
||||
|
||||
@staticmethod
|
||||
def from_bytes(b):
|
||||
"""Convert a compressed or uncompressed encoding to a group element."""
|
||||
assert len(b) in (33, 65)
|
||||
if len(b) == 33:
|
||||
if b[0] != 2 and b[0] != 3:
|
||||
return None
|
||||
x = FE.from_bytes(b[1:])
|
||||
if x is None:
|
||||
return None
|
||||
r = GE.lift_x(x)
|
||||
if r is None:
|
||||
return None
|
||||
if b[0] == 3:
|
||||
r = -r
|
||||
return r
|
||||
else:
|
||||
if b[0] != 4:
|
||||
return None
|
||||
x = FE.from_bytes(b[1:33])
|
||||
y = FE.from_bytes(b[33:])
|
||||
if y**2 != x**3 + 7:
|
||||
return None
|
||||
return GE(x, y)
|
||||
|
||||
@staticmethod
|
||||
def from_bytes_xonly(b):
|
||||
"""Convert a point given in xonly encoding to a group element."""
|
||||
assert len(b) == 32
|
||||
x = FE.from_bytes(b)
|
||||
if x is None:
|
||||
return None
|
||||
return GE.lift_x(x)
|
||||
|
||||
@staticmethod
|
||||
def is_valid_x(x):
|
||||
"""Determine whether the provided field element is a valid X coordinate."""
|
||||
return (FE(x)**3 + 7).is_square()
|
||||
|
||||
def __str__(self):
|
||||
"""Convert this group element to a string."""
|
||||
if self.infinity:
|
||||
return "(inf)"
|
||||
return f"({self.x},{self.y})"
|
||||
|
||||
def __repr__(self):
|
||||
"""Get a string representation for this group element."""
|
||||
if self.infinity:
|
||||
return "GE()"
|
||||
return f"GE(0x{int(self.x):x},0x{int(self.y):x})"
|
||||
|
||||
# The secp256k1 generator point
|
||||
G = GE.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
|
||||
|
||||
|
||||
class FastGEMul:
|
||||
"""Table for fast multiplication with a constant group element.
|
||||
|
||||
Speed up scalar multiplication with a fixed point P by using a precomputed lookup table with
|
||||
its powers of 2:
|
||||
|
||||
table = [P, 2*P, 4*P, (2^3)*P, (2^4)*P, ..., (2^255)*P]
|
||||
|
||||
During multiplication, the points corresponding to each bit set in the scalar are added up,
|
||||
i.e. on average ~128 point additions take place.
|
||||
"""
|
||||
|
||||
def __init__(self, p):
|
||||
self.table = [p] # table[i] = (2^i) * p
|
||||
for _ in range(255):
|
||||
p = p + p
|
||||
self.table.append(p)
|
||||
|
||||
def mul(self, a):
|
||||
result = GE()
|
||||
a = a % GE.ORDER
|
||||
for bit in range(a.bit_length()):
|
||||
if a & (1 << bit):
|
||||
result += self.table[bit]
|
||||
return result
|
||||
|
||||
# Precomputed table with multiples of G for fast multiplication
|
||||
FAST_G = FastGEMul(G)
|
||||
65
test/functional/test_framework/crypto/siphash.py
Normal file
65
test/functional/test_framework/crypto/siphash.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016-2022 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""SipHash-2-4 implementation.
|
||||
|
||||
This implements SipHash-2-4. For convenience, an interface taking 256-bit
|
||||
integers is provided in addition to the one accepting generic data.
|
||||
"""
|
||||
|
||||
def rotl64(n, b):
|
||||
return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b
|
||||
|
||||
|
||||
def siphash_round(v0, v1, v2, v3):
|
||||
v0 = (v0 + v1) & ((1 << 64) - 1)
|
||||
v1 = rotl64(v1, 13)
|
||||
v1 ^= v0
|
||||
v0 = rotl64(v0, 32)
|
||||
v2 = (v2 + v3) & ((1 << 64) - 1)
|
||||
v3 = rotl64(v3, 16)
|
||||
v3 ^= v2
|
||||
v0 = (v0 + v3) & ((1 << 64) - 1)
|
||||
v3 = rotl64(v3, 21)
|
||||
v3 ^= v0
|
||||
v2 = (v2 + v1) & ((1 << 64) - 1)
|
||||
v1 = rotl64(v1, 17)
|
||||
v1 ^= v2
|
||||
v2 = rotl64(v2, 32)
|
||||
return (v0, v1, v2, v3)
|
||||
|
||||
|
||||
def siphash(k0, k1, data):
|
||||
assert type(data) is bytes
|
||||
v0 = 0x736f6d6570736575 ^ k0
|
||||
v1 = 0x646f72616e646f6d ^ k1
|
||||
v2 = 0x6c7967656e657261 ^ k0
|
||||
v3 = 0x7465646279746573 ^ k1
|
||||
c = 0
|
||||
t = 0
|
||||
for d in data:
|
||||
t |= d << (8 * (c % 8))
|
||||
c = (c + 1) & 0xff
|
||||
if (c & 7) == 0:
|
||||
v3 ^= t
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0 ^= t
|
||||
t = 0
|
||||
t = t | (c << 56)
|
||||
v3 ^= t
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0 ^= t
|
||||
v2 ^= 0xff
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
|
||||
return v0 ^ v1 ^ v2 ^ v3
|
||||
|
||||
|
||||
def siphash256(k0, k1, num):
|
||||
assert type(num) is int
|
||||
return siphash(k0, k1, num.to_bytes(32, 'little'))
|
||||
@@ -0,0 +1,33 @@
|
||||
u,x,case0_t,case1_t,case2_t,case3_t,case4_t,case5_t,case6_t,case7_t,comment
|
||||
05ff6bdad900fc3261bc7fe34e2fb0f569f06e091ae437d3a52e9da0cbfb9590,80cdf63774ec7022c89a5a8558e373a279170285e0ab27412dbce510bdfe23fc,,,45654798ece071ba79286d04f7f3eb1c3f1d17dd883610f2ad2efd82a287466b,0aeaa886f6b76c7158452418cbf5033adc5747e9e9b5d3b2303db96936528557,,,ba9ab867131f8e4586d792fb080c14e3c0e2e82277c9ef0d52d1027c5d78b5c4,f51557790948938ea7badbe7340afcc523a8b816164a2c4dcfc24695c9ad76d8,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&ok;case7:ok
|
||||
1737a85f4c8d146cec96e3ffdca76d9903dcf3bd53061868d478c78c63c2aa9e,39e48dd150d2f429be088dfd5b61882e7e8407483702ae9a5ab35927b15f85ea,1be8cc0b04be0c681d0c6a68f733f82c6c896e0c8a262fcd392918e303a7abf4,605b5814bf9b8cb066667c9e5480d22dc5b6c92f14b4af3ee0a9eb83b03685e3,,,e41733f4fb41f397e2f3959708cc07d3937691f375d9d032c6d6e71bfc58503b,9fa4a7eb4064734f99998361ab7f2dd23a4936d0eb4b50c11f56147b4fc9764c,,,case0:ok;case1:ok;case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
|
||||
1aaa1ccebf9c724191033df366b36f691c4d902c228033ff4516d122b2564f68,c75541259d3ba98f207eaa30c69634d187d0b6da594e719e420f4898638fc5b0,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(q)];case7:bad[non_square(q)]
|
||||
2323a1d079b0fd72fc8bb62ec34230a815cb0596c2bfac998bd6b84260f5dc26,239342dfb675500a34a196310b8d87d54f49dcac9da50c1743ceab41a7b249ff,f63580b8aa49c4846de56e39e1b3e73f171e881eba8c66f614e67e5c975dfc07,b6307b332e699f1cf77841d90af25365404deb7fed5edb3090db49e642a156b6,,,09ca7f4755b63b7b921a91c61e4c18c0e8e177e145739909eb1981a268a20028,49cf84ccd19660e30887be26f50dac9abfb2148012a124cf6f24b618bd5ea579,,,case0:ok;case1:ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
|
||||
2dc90e640cb646ae9164c0b5a9ef0169febe34dc4437d6e46acb0e27e219d1e8,d236f19bf349b9516e9b3f4a5610fe960141cb23bbc8291b9534f1d71de62a47,e69df7d9c026c36600ebdf588072675847c0c431c8eb730682533e964b6252c9,4f18bbdf7c2d6c5f818c18802fa35cd069eaa79fff74e4fc837c80d93fece2f8,,,196208263fd93c99ff1420a77f8d98a7b83f3bce37148cf97dacc168b49da966,b0e7442083d293a07e73e77fd05ca32f96155860008b1b037c837f25c0131937,,,case0:ok;case1:info[v=0]&ok;case2:bad[non_square(q)];case3:bad[non_square(q)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(q)];case7:bad[non_square(q)]
|
||||
3edd7b3980e2f2f34d1409a207069f881fda5f96f08027ac4465b63dc278d672,053a98de4a27b1961155822b3a3121f03b2a14458bd80eb4a560c4c7a85c149c,,,b3dae4b7dcf858e4c6968057cef2b156465431526538199cf52dc1b2d62fda30,4aa77dd55d6b6d3cfa10cc9d0fe42f79232e4575661049ae36779c1d0c666d88,,,4c251b482307a71b39697fa8310d4ea9b9abcead9ac7e6630ad23e4c29d021ff,b558822aa29492c305ef3362f01bd086dcd1ba8a99efb651c98863e1f3998ea7,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:ok
|
||||
4295737efcb1da6fb1d96b9ca7dcd1e320024b37a736c4948b62598173069f70,fa7ffe4f25f88362831c087afe2e8a9b0713e2cac1ddca6a383205a266f14307,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
|
||||
587c1a0cee91939e7f784d23b963004a3bf44f5d4e32a0081995ba20b0fca59e,2ea988530715e8d10363907ff25124524d471ba2454d5ce3be3f04194dfd3a3c,cfd5a094aa0b9b8891b76c6ab9438f66aa1c095a65f9f70135e8171292245e74,a89057d7c6563f0d6efa19ae84412b8a7b47e791a191ecdfdf2af84fd97bc339,475d0ae9ef46920df07b34117be5a0817de1023e3cc32689e9be145b406b0aef,a0759178ad80232454f827ef05ea3e72ad8d75418e6d4cc1cd4f5306c5e7c453,302a5f6b55f464776e48939546bc709955e3f6a59a0608feca17e8ec6ddb9dbb,576fa82839a9c0f29105e6517bbed47584b8186e5e6e132020d507af268438f6,b8a2f51610b96df20f84cbee841a5f7e821efdc1c33cd9761641eba3bf94f140,5f8a6e87527fdcdbab07d810fa15c18d52728abe7192b33e32b0acf83a1837dc,case0:ok;case1:ok;case2:ok;case3:ok;case4:ok;case5:ok;case6:ok;case7:ok
|
||||
5fa88b3365a635cbbcee003cce9ef51dd1a310de277e441abccdb7be1e4ba249,79461ff62bfcbcac4249ba84dd040f2cec3c63f725204dc7f464c16bf0ff3170,,,6bb700e1f4d7e236e8d193ff4a76c1b3bcd4e2b25acac3d51c8dac653fe909a0,f4c73410633da7f63a4f1d55aec6dd32c4c6d89ee74075edb5515ed90da9e683,,,9448ff1e0b281dc9172e6c00b5893e4c432b1d4da5353c2ae3725399c016f28f,0b38cbef9cc25809c5b0e2aa513922cd3b39276118bf8a124aaea125f25615ac,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:info[v=0]&ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:info[v=0]&ok
|
||||
6fb31c7531f03130b42b155b952779efbb46087dd9807d241a48eac63c3d96d6,56f81be753e8d4ae4940ea6f46f6ec9fda66a6f96cc95f506cb2b57490e94260,,,59059774795bdb7a837fbe1140a5fa59984f48af8df95d57dd6d1c05437dcec1,22a644db79376ad4e7b3a009e58b3f13137c54fdf911122cc93667c47077d784,,,a6fa688b86a424857c8041eebf5a05a667b0b7507206a2a82292e3f9bc822d6e,dd59bb2486c8952b184c5ff61a74c0ecec83ab0206eeedd336c9983a8f8824ab,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:ok;case3:info[v=0]&ok;case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:ok;case7:info[v=0]&ok
|
||||
704cd226e71cb6826a590e80dac90f2d2f5830f0fdf135a3eae3965bff25ff12,138e0afa68936ee670bd2b8db53aedbb7bea2a8597388b24d0518edd22ad66ec,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
|
||||
725e914792cb8c8949e7e1168b7cdd8a8094c91c6ec2202ccd53a6a18771edeb,8da16eb86d347376b6181ee9748322757f6b36e3913ddfd332ac595d788e0e44,dd357786b9f6873330391aa5625809654e43116e82a5a5d82ffd1d6624101fc4,a0b7efca01814594c59c9aae8e49700186ca5d95e88bcc80399044d9c2d8613d,,,22ca8879460978cccfc6e55a9da7f69ab1bcee917d5a5a27d002e298dbefdc6b,5f481035fe7eba6b3a63655171b68ffe7935a26a1774337fc66fbb253d279af2,,,case0:ok;case1:info[v=0]&ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:info[v=0]&ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
|
||||
78fe6b717f2ea4a32708d79c151bf503a5312a18c0963437e865cc6ed3f6ae97,8701948e80d15b5cd8f72863eae40afc5aced5e73f69cbc8179a33902c094d98,,,,,,,,,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(q)];case3:bad[non_square(q)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(q)];case7:bad[non_square(q)]
|
||||
7c37bb9c5061dc07413f11acd5a34006e64c5c457fdb9a438f217255a961f50d,5c1a76b44568eb59d6789a7442d9ed7cdc6226b7752b4ff8eaf8e1a95736e507,,,b94d30cd7dbff60b64620c17ca0fafaa40b3d1f52d077a60a2e0cafd145086c2,,,,46b2cf32824009f49b9df3e835f05055bf4c2e0ad2f8859f5d1f3501ebaf756d,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
|
||||
82388888967f82a6b444438a7d44838e13c0d478b9ca060da95a41fb94303de6,29e9654170628fec8b4972898b113cf98807f4609274f4f3140d0674157c90a0,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
|
||||
91298f5770af7a27f0a47188d24c3b7bf98ab2990d84b0b898507e3c561d6472,144f4ccbd9a74698a88cbf6fd00ad886d339d29ea19448f2c572cac0a07d5562,e6a0ffa3807f09dadbe71e0f4be4725f2832e76cad8dc1d943ce839375eff248,837b8e68d4917544764ad0903cb11f8615d2823cefbb06d89049dbabc69befda,,,195f005c7f80f6252418e1f0b41b8da0d7cd189352723e26bc317c6b8a1009e7,7c8471972b6e8abb89b52f6fc34ee079ea2d7dc31044f9276fb6245339640c55,,,case0:ok;case1:ok;case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
|
||||
b682f3d03bbb5dee4f54b5ebfba931b4f52f6a191e5c2f483c73c66e9ace97e1,904717bf0bc0cb7873fcdc38aa97f19e3a62630972acff92b24cc6dda197cb96,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:bad[non_square(s)]
|
||||
c17ec69e665f0fb0dbab48d9c2f94d12ec8a9d7eacb58084833091801eb0b80b,147756e66d96e31c426d3cc85ed0c4cfbef6341dd8b285585aa574ea0204b55e,6f4aea431a0043bdd03134d6d9159119ce034b88c32e50e8e36c4ee45eac7ae9,fd5be16d4ffa2690126c67c3ef7cb9d29b74d397c78b06b3605fda34dc9696a6,5e9c60792a2f000e45c6250f296f875e174efc0e9703e628706103a9dd2d82c7,,90b515bce5ffbc422fcecb2926ea6ee631fcb4773cd1af171c93b11aa1538146,02a41e92b005d96fed93983c1083462d648b2c683874f94c9fa025ca23696589,a1639f86d5d0fff1ba39daf0d69078a1e8b103f168fc19d78f9efc5522d27968,,case0:ok;case1:ok;case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:ok;case5:ok;case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
|
||||
c25172fc3f29b6fc4a1155b8575233155486b27464b74b8b260b499a3f53cb14,1ea9cbdb35cf6e0329aa31b0bb0a702a65123ed008655a93b7dcd5280e52e1ab,,,7422edc7843136af0053bb8854448a8299994f9ddcefd3a9a92d45462c59298a,78c7774a266f8b97ea23d05d064f033c77319f923f6b78bce4e20bf05fa5398d,,,8bdd12387bcec950ffac4477abbb757d6666b06223102c5656d2bab8d3a6d2a5,873888b5d990746815dc2fa2f9b0fcc388ce606dc09487431b1df40ea05ac2a2,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:ok;case7:ok
|
||||
cab6626f832a4b1280ba7add2fc5322ff011caededf7ff4db6735d5026dc0367,2b2bef0852c6f7c95d72ac99a23802b875029cd573b248d1f1b3fc8033788eb6,,,,,,,,,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
|
||||
d8621b4ffc85b9ed56e99d8dd1dd24aedcecb14763b861a17112dc771a104fd2,812cabe972a22aa67c7da0c94d8a936296eb9949d70c37cb2b2487574cb3ce58,fbc5febc6fdbc9ae3eb88a93b982196e8b6275a6d5a73c17387e000c711bd0e3,8724c96bd4e5527f2dd195a51c468d2d211ba2fac7cbe0b4b3434253409fb42d,,,043a014390243651c147756c467de691749d8a592a58c3e8c781fff28ee42b4c,78db36942b1aad80d22e6a5ae3b972d2dee45d0538341f4b4cbcbdabbf604802,,,case0:ok;case1:ok;case2:bad[non_square(s)];case3:bad[non_square(s)];case4:ok;case5:ok;case6:bad[non_square(s)];case7:bad[non_square(s)]
|
||||
da463164c6f4bf7129ee5f0ec00f65a675a8adf1bd931b39b64806afdcda9a22,25b9ce9b390b408ed611a0f13ff09a598a57520e426ce4c649b7f94f2325620d,,,,,,,,,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:bad[non_square(s)];case3:bad[non_square(s)];case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:bad[non_square(s)];case7:bad[non_square(s)]
|
||||
dafc971e4a3a7b6dcfb42a08d9692d82ad9e7838523fcbda1d4827e14481ae2d,250368e1b5c58492304bd5f72696d27d526187c7adc03425e2b7d81dbb7e4e02,,,370c28f1be665efacde6aa436bf86fe21e6e314c1e53dd040e6c73a46b4c8c49,cd8acee98ffe56531a84d7eb3e48fa4034206ce825ace907d0edf0eaeb5e9ca2,,,c8f3d70e4199a105321955bc9407901de191ceb3e1ac22fbf1938c5a94b36fe6,327531167001a9ace57b2814c1b705bfcbdf9317da5316f82f120f1414a15f8d,case0:bad[non_square(s)];case1:info[v=0]&bad[non_square(s)];case2:ok;case3:ok;case4:bad[non_square(s)];case5:info[v=0]&bad[non_square(s)];case6:ok;case7:ok
|
||||
e0294c8bc1a36b4166ee92bfa70a5c34976fa9829405efea8f9cd54dcb29b99e,ae9690d13b8d20a0fbbf37bed8474f67a04e142f56efd78770a76b359165d8a1,,,dcd45d935613916af167b029058ba3a700d37150b9df34728cb05412c16d4182,,,,232ba26ca9ec6e950e984fd6fa745c58ff2c8eaf4620cb8d734fabec3e92baad,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[q=0]&info[X=0]&ok;case3:info[q=0]&bad[r=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[q=0]&info[X=0]&ok;case7:info[q=0]&bad[r=0]
|
||||
e148441cd7b92b8b0e4fa3bd68712cfd0d709ad198cace611493c10e97f5394e,164a639794d74c53afc4d3294e79cdb3cd25f99f6df45c000f758aba54d699c0,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[non_square(s)];case3:info[v=0]&bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[non_square(s)];case7:info[v=0]&bad[non_square(s)]
|
||||
e4b00ec97aadcca97644d3b0c8a931b14ce7bcf7bc8779546d6e35aa5937381c,94e9588d41647b3fcc772dc8d83c67ce3be003538517c834103d2cd49d62ef4d,c88d25f41407376bb2c03a7fffeb3ec7811cc43491a0c3aac0378cdc78357bee,51c02636ce00c2345ecd89adb6089fe4d5e18ac924e3145e6669501cd37a00d4,205b3512db40521cb200952e67b46f67e09e7839e0de44004138329ebd9138c5,58aab390ab6fb55c1d1b80897a207ce94a78fa5b4aa61a33398bcae9adb20d3e,3772da0bebf8c8944d3fc5800014c1387ee33bcb6e5f3c553fc8732287ca8041,ae3fd9c931ff3dcba132765249f7601b2a1e7536db1ceba19996afe22c85fb5b,dfa4caed24bfade34dff6ad1984b90981f6187c61f21bbffbec7cd60426ec36a,a7554c6f54904aa3e2e47f7685df8316b58705a4b559e5ccc6743515524deef1,case0:ok;case1:ok;case2:ok;case3:info[v=0]&ok;case4:ok;case5:ok;case6:ok;case7:info[v=0]&ok
|
||||
e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5,e5bbb9ef360d0a501618f0067d36dceb75f5be9a620232aa9fd5139d0863fde5,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:bad[s=0];case3:bad[s=0];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:bad[s=0];case7:bad[s=0]
|
||||
e6bcb5c3d63467d490bfa54fbbc6092a7248c25e11b248dc2964a6e15edb1457,19434a3c29cb982b6f405ab04439f6d58db73da1ee4db723d69b591da124e7d8,67119877832ab8f459a821656d8261f544a553b89ae4f25c52a97134b70f3426,ffee02f5e649c07f0560eff1867ec7b32d0e595e9b1c0ea6e2a4fc70c97cd71f,b5e0c189eb5b4bacd025b7444d74178be8d5246cfa4a9a207964a057ee969992,5746e4591bf7f4c3044609ea372e908603975d279fdef8349f0b08d32f07619d,98ee67887cd5470ba657de9a927d9e0abb5aac47651b0da3ad568eca48f0c809,0011fd0a19b63f80fa9f100e7981384cd2f1a6a164e3f1591d5b038e36832510,4a1f3e7614a4b4532fda48bbb28be874172adb9305b565df869b5fa71169629d,a8b91ba6e4080b3cfbb9f615c8d16f79fc68a2d8602107cb60f4f72bd0f89a92,case0:ok;case1:info[v=0]&ok;case2:ok;case3:ok;case4:ok;case5:info[v=0]&ok;case6:ok;case7:ok
|
||||
f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6,f28fba64af766845eb2f4302456e2b9f8d80affe57e7aae42738d7cddb1c2ce6,4f867ad8bb3d840409d26b67307e62100153273f72fa4b7484becfa14ebe7408,5bbc4f59e452cc5f22a99144b10ce8989a89a995ec3cea1c91ae10e8f721bb5d,,,b079852744c27bfbf62d9498cf819deffeacd8c08d05b48b7b41305db1418827,a443b0a61bad33a0dd566ebb4ef317676576566a13c315e36e51ef1608de40d2,,,case0:ok;case1:ok;case2:bad[s=0];case3:bad[s=0];case4:ok;case5:ok;case6:bad[s=0];case7:bad[s=0]
|
||||
f455605bc85bf48e3a908c31023faf98381504c6c6d3aeb9ede55f8dd528924d,d31fbcd5cdb798f6c00db6692f8fe8967fa9c79dd10958f4a194f01374905e99,,,0c00c5715b56fe632d814ad8a77f8e66628ea47a6116834f8c1218f3a03cbd50,df88e44fac84fa52df4d59f48819f18f6a8cd4151d162afaf773166f57c7ff46,,,f3ff3a8ea4a9019cd27eb527588071999d715b859ee97cb073ede70b5fc33edf,20771bb0537b05ad20b2a60b77e60e7095732beae2e9d505088ce98fa837fce9,case0:bad[non_square(s)];case1:bad[non_square(s)];case2:info[v=0]&ok;case3:ok;case4:bad[non_square(s)];case5:bad[non_square(s)];case6:info[v=0]&ok;case7:ok
|
||||
f58cd4d9830bad322699035e8246007d4be27e19b6f53621317b4f309b3daa9d,78ec2b3dc0948de560148bbc7c6dc9633ad5df70a5a5750cbed721804f082a3b,6c4c580b76c7594043569f9dae16dc2801c16a1fbe12860881b75f8ef929bce5,94231355e7385c5f25ca436aa64191471aea4393d6e86ab7a35fe2afacaefd0d,dff2a1951ada6db574df834048149da3397a75b829abf58c7e69db1b41ac0989,a52b66d3c907035548028bf804711bf422aba95f1a666fc86f4648e05f29caae,93b3a7f48938a6bfbca9606251e923d7fe3e95e041ed79f77e48a07006d63f4a,6bdcecaa18c7a3a0da35bc9559be6eb8e515bc6c291795485ca01d4f5350ff22,200d5e6ae525924a8b207cbfb7eb625cc6858a47d6540a73819624e3be53f2a6,5ad4992c36f8fcaab7fd7407fb8ee40bdd5456a0e599903790b9b71ea0d63181,case0:ok;case1:ok;case2:info[v=0]&ok;case3:ok;case4:ok;case5:ok;case6:info[v=0]&ok;case7:ok
|
||||
fd7d912a40f182a3588800d69ebfb5048766da206fd7ebc8d2436c81cbef6421,8d37c862054debe731694536ff46b273ec122b35a9bf1445ac3c4ff9f262c952,,,,,,,,,case0:bad[valid_x(-x-u)];case1:bad[valid_x(-x-u)];case2:info[v=0]&bad[non_square(s)];case3:bad[non_square(s)];case4:bad[valid_x(-x-u)];case5:bad[valid_x(-x-u)];case6:info[v=0]&bad[non_square(s)];case7:bad[non_square(s)]
|
||||
|
Reference in New Issue
Block a user