def test_int(): x = CF(3) y = CF(4) assert x + y assert x - y assert x**2 assert x * y assert x / y
def test_complex(): x = CF(1 + 2j) y = CF(1 + 3j) assert x + y assert x * y assert (-x).__class__ == x.__class__ assert x + (-y) assert x - y
def sign(priv: CF, m: str) -> SigType: ''' https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v ''' k = CF(random_privkey()) z = CF(to_sha256int(m)) p = G @ k r, y = CF(p.value[0]), CF(p.value[1]) s = (z + priv * r) / k v = CF(27 + y.value % 2) return v, r, s
def open(self): c, a, mac = self.c m, d, z = self.d alpha = CF(to_sha256int(gen_address(c))) assert mac == hmac.new(str(d[1].value).encode(), encode_pubkey(a).encode()).hexdigest() assert self.S.proof return m
def proof(): priv = random_privkey() m = 'test' k = CF(random_privkey()) z = CF(to_sha256int(m)) r = CF((G @ k).value[0]) s = z / k + priv * r / k assert k == z / s + priv * r / s assert G @ k == G @ (z / s + priv * r / s) assert G @ k == G @ (z / s) + G @ priv @ (r / s) pub = G @ priv assert pub == pubkey(priv) assert G @ k == G @ (z / s) + pub @ (r / s) u1 = z / s u2 = r / s assert G @ k == G @ u1 + pub @ u2
def verify_msghash(pub: ECG, sig: tuple, mhash: int): if len(sig) == 2: r, s = sig else: v, r, s = sig z = CF(mhash) u1 = z / s u2 = r / s rp = G @ u1 + pub @ u2 return r == rp.value[0]
def recover(sig: tuple, mhash: int): v, r, s = sig x = F(r) xcubedaxb = x**3 + F(A) * x + F(B) beta = pow(xcubedaxb.value, (P + 1) // 4, P) if v.value % 2 ^ beta % 2: y = beta print('case 1') else: print('case 2') y = P - beta Gz = G @ (F(N) - F(mhash)) Xy = ECG((F(x), F(y))) @ s Qr = Gz + Xy Q = Qr @ ~CF(r) return Q
def commit(self, m, ak): pk, vk, h = self.key com = PedersonCommitment(H, G, pk, ak) # (𝑐,𝑑)=𝐻𝑆𝑐𝑜𝑚𝑚𝑖𝑡𝑝𝑘(𝑎𝑘) c, d = com.C, com.D # α=ℎ(𝑐) alpha = CF(to_sha256int(gen_address(c))) # Now we simulate a proof of knowledge of a signature on 𝛼 with challenge 𝑚 S = PedersonCommitment(H, G, vk, alpha) r1, r2 = randfield(vk.functor), randfield(vk.functor) a = S.commit(r1, r2) z = S.challenge(m) self.S = S # Finally, we compute 𝑚𝑎𝑐=𝑀𝐴𝐶𝑎𝑘(𝑎). mac = hmac.new(str(ak.value).encode(), encode_pubkey(a).encode()).hexdigest() self.c = (c, a, mac) self.d = (m, d , z)
def random_privkey() -> CF: return CF(random.randint(1, N))
def verify(pubkey: str, sig: str, msg: str): pubkey = decode_pubkey(pubkey) sig = sig_decode(sig) sig = CF(sig[0]._value), CF(sig[1]._value) return ecdsa.verify(pubkey, sig, msg)
def from_sigtype(sig): return tuple([CF(v) for v in sig])
# from klefki.types.algebra.concrete import EllipticCurveCyclicSubgroupSecp256k1 as ECC from klefki.types.algebra.concrete import EllipticCurveGroupSecp256k1 as Cruve from klefki.types.algebra.concrete import FiniteFieldCyclicSecp256k1 as CF from klefki.types.algebra.concrete import FiniteFieldSecp256k1 as F from klefki.types.algebra.utils import randfield from klefki.bitcoin.address import gen_address from klefki.utils import to_sha256int import hmac from klefki.bitcoin.public import encode_pubkey from klefki.utils import int_to_byte from klefki.zkp.commitment import Commitment, Sigma from klefki.zkp.pedersen import PedersonCommitment G = ECC.G H = Cruve.lift_x(CF(to_sha256int("hello NIRNCS"))) def keygen(F): pk = randfield(F) vk = F(to_sha256int(str(pk.value))) h = gen_address return (pk, vk, h) class NMCommitment(Commitment): def __init__(self, G, H, key=None): if not key:
def test_add(): assert G - G == CG(0) assert G + G == G @ CF(2)
def to_cf(a: int): return CF(a)
def to_cf(a: int) -> CF: return CF(a)
def decode_privkey(key: str) -> CF: return CF(int(key, 16))
def from_bytes(a): return ECG([ CF(byte_to_int(a[:1]) - 2), CF(byte_to_int(a[1:])) ])