示例#1
0
def pedersen_prover(C, X, x, r, rnd_bytes=os.urandom, RO=sha2):
    """
    Params: 
       x and r are elements of Fp
       C,X are Points
    Returns:
       prf, of the form (KX,KC,sx,sr)
    """
    assert X == x * G
    assert C == x * G + r * H

    # TODO: fill in your code here (10 points)

    # blinding factor
    kx = uint256_from_str(rnd_bytes(32)) % order
    kr = uint256_from_str(rnd_bytes(32)) % order

    # commitment
    KX = kx * G
    KC = kx * G + kr * H

    # receive challenge from random oracle
    c = uint256_from_str(RO(ser(KX) + ser(KC)))

    # responses
    sx = Fp(kx + c * x)
    sr = Fp(kr + c * r)

    return (KX, KC, sx, sr)
示例#2
0
def arith_prover(a, b, A, B, C, rnd_bytes=os.urandom, RO=sha2):
    """
    Params: 
       a and b are elements of Fp
       A, B, C are Points
    Returns:
       prf, of the form (KA,KB,KC,sa,sb)

    Must satisfy verify_proof2(A, B, C, prf)
    Must be zero-knowledge
    """
    assert a * G == A
    assert b * G == B
    assert (a * (b - 3)) * G == C

    # TODO: fill in your code here (10 points)
    ka = uint256_from_str(rnd_bytes(32)) % order
    kb = uint256_from_str(rnd_bytes(32)) % order

    KA = ka * G
    KB = kb * G
    KC = kb * A
    c = uint256_from_str(RO(ser(KA) + ser(KB) + ser(KC)))

    sa = Fp(ka + a * c)
    sb = Fp(kb + b * c)

    return (KA, KB, KC, sa, sb)
示例#3
0
def dlog_extractor(A, Adv):
    assert type(A) is Point

    ## Step 1: run the adversary to generate a proof while recording
    ## the random bits and oracle queries

    # TODO: Fill your code in here

    i = 0
    l = {}
    found = False
    found2 = False
    mapping = {}

    def RO1(s):
        assert type(s) is str
        nonlocal mapping
        if not s in mapping:
            mapping[s] = os.urandom(32)
        return mapping[s]

    def RO2(s):
        assert type(s) is str
        nonlocal mapping
        if not found2:
            mapping[s] = os.urandom(32)
        return mapping[s]

    def rand(x):
        nonlocal i, l, found
        if x == 32 and found:
            return l[i]
        elif x == 32 and not found:
            i += 1
            r = os.urandom(x)
            l[i] = r
            return r
        else:
            return os.urandom(x)

    (K1, s1) = Adv(A, rnd_bytes=rand, RO=RO1)
    found = True
    c1 = uint256_from_str(RO1(ser(K1)))
    # print("c1",c1,"\n","K1",K1)
    ## Step 2: run the adversary again, replaying the random bits,
    ## and intercepting the call to the random oracle

    # TODO: Fill your code in here (5 points)
    (K2, s2) = Adv(A, rnd_bytes=rand, RO=RO2)
    found2 = True
    c2 = uint256_from_str(RO2(ser(K2)))
    # print("c2",c2,"\n","K2",K2)

    ## Step 3: Extract a witness from the two proofs and oracle queries
    # TODO: Fill your code in here (5 points)
    return Fp(s1 - s2) / Fp(c1 - c2)
示例#4
0
def pedersen_verifier(C, X, prf, RO=sha2):
    (KX, KC, sx, sr) = prf
    assert type(KX) == type(KC) == Point
    assert type(sx) == type(sr) == Fp

    # Recompute c w/ the information given
    c = uint256_from_str(RO(ser(KX) + ser(KC)))

    assert sx.n * G == KX + c * X
    assert sx.n * G + sr.n * H == KC + c * C
    return True
示例#5
0
def arith_verifier(A, B, C, prf, rnd_bytes=os.urandom, RO=sha2):
    (KA, KB, KC, sa, sb) = prf
    assert type(KA) == type(KB) == type(KC) == Point
    assert type(sa) == type(sb) == Fp

    # TODO: fill in your code here (10 points)
    c = uint256_from_str(RO(ser(KA) + ser(KB) + ser(KC)))

    assert sa.n * G == KA + c * A
    assert sb.n * G == KB + c * B
    assert sb.n * A == KC + c * (C + 3 * A)

    return True
示例#6
0
def OR_verifier(A, B, prf, RO=sha2):
    (KA, KB, sa, sb, ca, cb) = prf
    assert type(KA) is type(KB) is Point
    assert type(sa) is type(sb) is Fp

    # Check the challenges are correctly constrained
    c = uint256_from_str(RO(ser(KA) + ser(KB)))
    assert (ca + cb) % p == c

    # Check each proof the same way
    assert sa.n * G == KA + ca * A
    assert sb.n * G == KB + cb * B

    return True
示例#7
0
def pedersen_test():

    x = uint256_from_str(os.urandom(32))
    X = x * G
    C, r = make_pedersen_commitment(x)

    prf = pedersen_prover(C, X, x, r)
    (KX, KC, sx, sr) = prf
    print(
        repr((ser(C), ser(KX), ser(KC), uint256_to_str(sx.n).encode('latin'),
              uint256_to_str(sr.n).encode('latin'))))

    assert pedersen_verifier(C, X, prf)
    print("Pedersen correctness test complete!")
示例#8
0
def schnorr_verify(X, m, sig, RO=sha2):
    assert type(X) is Point
    assert type(sig) is bytes and len(sig) is 65
    (K, s) = deser(sig[:33].hex()), uint256_from_str(sig[33:])
    c = uint256_from_str(RO(ser(K) + sha2(m).hex()))
    assert s * G == K + c * X
    return True
示例#9
0
def pedersen_vector_prover(C_arr, x_arr, r_arr, rnd_bytes=os.urandom, RO=sha2):
    """
    Params: 
       x_arr, r_arr are arrays of elements in Fp
       C_arr are arrays of Points
    Returns:
       prf, of the form (K,sx,sr) where K is points and sx and sr are points in Fp 
       Note that here you are able to prove that knowledge of n points with only communicating 1 ppints and 2 scalars.
    """

    # Make sure all commitments are correct
    for C_elem, x_elem, r_elem in zip(C_arr, x_arr, r_arr):
        assert C_elem == x_elem * G + r_elem * H

    # TODO: Your code goes here: 10 points
    # commitment
    K = C_arr[0]

    c = Fp(uint256_from_str(RO(ser(K))))
    sx = x_arr[0]
    sr = r_arr[0]
    e = c
    # responses
    for i in range(len(C_arr)):
        sx = Fp(sx + e.n * x_arr[i])
        sr = Fp(sr + e.n * r_arr[i])
        e = Fp(e * c)
        # print(e.n)
    return (K, sx, sr)
示例#10
0
def schnorr_sign(x, m, rnd_bytes=os.urandom, RO=sha2):
    assert type(x) is bytes
    assert type(m) is str

    # TODO: Your code goes here (10 points)
    k = uint256_from_str(rnd_bytes(32)) % order

    K = k * G

    c = uint256_from_str(RO(ser(K) + sha2(m).hex()))

    x = uint256_from_str(x)

    s = Fp(k + c * x)

    return bytes.fromhex(ser(K)) + uint256_to_str(s.n)
示例#11
0
def sender_round3(M0, M1, a, B, RO=sha2):
    """
    Inputs:
       M0 and M1, each an element in Fp
       kR: the secret saved from sender_round1
    Returns:
       (e0,e1), the two ciphertexts
    """
    assert type(a) is Fp
    assert type(M0) is str and type(M1) is str
    assert len(M0) == len(M1) == 16
    # TODO: your code goes here
    k0 = RO(ser(a.n * B))
    k1 = RO(ser(a.n * (B - a.n * G)))
    e0 = encrypt(k0, M0)
    e1 = encrypt(k1, M1)
    return e0, e1
示例#12
0
def dlog_verifier(A, prf, RO=sha2):
    (K, s) = prf
    assert type(A) is type(K) is Point
    assert type(s) is Fp

    # Recompute c w/ the information given
    c = uint256_from_str(RO(ser(K)))

    # Check the verification condition
    assert s.n * G == K + c * A
    return True
示例#13
0
def OR_prover(A, B, x, rnd_bytes=os.urandom, RO=sha2):
    assert x * G == A or x * G == B

    # TODO: Fill your code in here (20 points)
    ka = uint256_from_str(rnd_bytes(32)) % order
    kb = uint256_from_str(rnd_bytes(32)) % order

    KA = ka * G
    KB = kb * G
    c = uint256_from_str(RO(ser(KA) + ser(KB)))

    if x * G != B:
        ca = c
        cb = x * order
    else:
        ca = x * order
        cb = c

    sa = Fp(ka + x * ca)
    sb = Fp(kb + x * cb)

    return (KA, KB, sa, sb, ca, cb)
示例#14
0
def dlog_prover(A, a, rnd_bytes=os.urandom, RO=sha2):
    assert a * G == A

    # blinding factor
    k = uint256_from_str(rnd_bytes(32)) % order

    # commitment
    K = k * G

    # Invoke the random oracle to receive a challenge
    c = uint256_from_str(RO(ser(K)))

    # response
    s = Fp(k + c * 124213421)

    return (K, s)
示例#15
0
def dlog_prover(A,
                a,
                k=uint256_from_str(os.urandom(32)) % order,
                rnd_bytes=os.urandom,
                RO=sha2):
    assert a * G == A

    # commitment
    K = k * G

    # Invoke the random oracle to receive a challenge
    c = uint256_from_str(RO(ser(K)))

    # response
    s = Fp(k + c * a)

    return (K, s)
示例#16
0
def pedersen_vector_verifier(C_arr, prf, rnd_bytes=os.urandom, RO=sha2):
    (C0, sx, sr) = prf

    assert type(C0) == Point
    assert type(sx) == type(sr) == Fp

    c = Fp(uint256_from_str(RO(ser(C0))))

    e = c
    C_final = C0
    for C_elem in C_arr:
        C_final = C_final + e.n * C_elem
        e = Fp(e * c)

    assert C_final == sx.n * G + sr.n * H

    return True
def receiver_round2(c, A, rnd_bytes=os.urandom, RO=sha2):
    """
    Inputs:
       c  a bit 0 or 1
       A  the round1 message from the sender
    Returns:
       (kR, B)
       B is sent to the sender,
       kR is the decryption key, stored and passed to sender_round4
    """
    assert c in (0, 1)
    assert type(A) is Point

    # TODO: Your code goes here
    b = Fp(uint256_from_str(rnd_bytes(32)) % order)
    B = b.n * G if c == 0 else A + b.n * G
    kR = RO(ser(b.n * A))

    return kR, B
示例#18
0
    def Adv(A, rnd_bytes, RO):
        assert A == a * G

        while True:
            # The "picky" prover loops until it is happy

            # Make a whimsical decision
            coin = rnd_bytes(1)
            if ord(coin) < 128: continue

            k = uint256_from_str(rnd_bytes(32)) % order
            K = k * G
            c = uint256_from_str(RO(ser(K)))

            # I only like challenges that end with 3 zero bits
            if c & 0b111 != 0: continue

            # OK I'm satisfied
            s = Fp(k + c * a)
            return (K, s)
示例#19
0
def dlog_simulator(A, rnd_bytes):
    """
    Returns:
    - (prf, transcript)
    - prf, a tuple of the form (K,s),
        where K is a Point
        and s is an element of Fp
    - transcript is an array consisting of elements of the form
        [...(q,h)...]
      where each q is a query (a string)
      and each h is the response (a 32-byte string)
    """
    # TODO: Fill in your code here (10 points)
    transcript = []
    h = rnd_bytes(32)
    c = uint256_from_str(h)
    s = uint256_from_str(rnd_bytes(32)) % order
    K = s * G - c * A
    q = ser(K)
    transcript.append((q, h))
    return ((K, Fp(s)), transcript)
示例#20
0
def dlog_test_simulator():
    rnd_bytes = os.urandom
    # Test with a randomly generated point on curve
    A = random_point(rnd_bytes=rnd_bytes)

    (prf, transcript) = dlog_simulator(A, rnd_bytes)

    # Unpack the proof
    K, s = prf
    assert type(K) is Point
    assert type(s) is Fp

    # Unpack oracle transcript (there should be just one query)
    assert len(transcript) == 1
    (q, h) = transcript[0]

    assert q == ser(K)
    c = uint256_from_str(h)

    # Check the verification condition
    assert s.n * G == K + c * A

    print("DLOG simulator test complete!")