Esempio n. 1
0
def test_dleq_parallel():
    α = [Scalar.random() for _ in range(10)]
    g = [G * Scalar.random() for _ in range(10)]
    x = [g[i] * α[i] for i in range(10)]
    h = [H * Scalar.random() for _ in range(10)]
    y = [h[i] * α[i] for i in range(10)]
    e, z = _DLEQ_prove(g, x, h, y, α)
    assert _DLEQ_verify(g, x, h, y, e, z)
Esempio n. 2
0
 def random(degree: int, secret: Optional[Scalar] = None) -> "Polynomial":
     """ Return a polynomial with random coefficients from Zq.
         p(x) = c_0 + c_1*x + ... c_{degree} * x^{degree}
     """
     if secret is None:
         coeffs = [Scalar.random() for i in range(degree + 1)]
     else:
         coeffs = [secret] + [Scalar.random() for i in range(degree)]
     return Polynomial(coeffs)
Esempio n. 3
0
def share_random_secret(
    receiver_public_keys: List[Point],
    recovery_threshold: int,
    secret_scalar: Optional[Scalar] = None
) -> Tuple[Scalar, List[Point], ShareCorrectnessProof]:
    """ generate a fresh random base secret s (or uses the provided one)
        computes share (s_1, ..., s_n) for S = h^s
        encrypts them with the public keys to obtain ŝ_1, ..., ŝ_n
        compute the verification information
        returns
         - the secret s (which can is used to reveal and verify S)
         - the encrypted shares ŝ_1, ..., ŝ_n
         - the share verification information, i.e. PROOF_D, which consists of
            - the commitments v_1, ..., v_n   (v_i = g^{s_i})
            - the (common) challenge e
            - the responses z_1, ..., z_n
    """
    num_receivers = len(receiver_public_keys)

    secret = secret_scalar or Scalar.random()
    poly = Polynomial.random(recovery_threshold - 1, secret)

    shares = [poly(i) for i in range(1, num_receivers + 1)]
    encrypted_shares = [
        pk * share for pk, share in zip(receiver_public_keys, shares)
    ]
    proof = prove_share_correctness(shares, encrypted_shares,
                                    receiver_public_keys)

    return secret, encrypted_shares, proof
Esempio n. 4
0
def _DLEQ_prove(g, x, h, y, α):
    """ Performs a the DLEQ NIZK protocol for the given values g, x, h, y and the exponent α.
        I.e. the prover shows that he knows α such that x = g^α and y = h^α holds.
        To perform the proving prodedure in parallel (but with a common challenge) g, x, h, y and α might be lists.
    """
    g, x, h, y, α = _listify(g, x, h, y, α)
    assert len(g) == len(x) == len(h) == len(y) == len(α)
    n = len(g)

    w = [Scalar.random() for _ in range(n)]  # w random element from Zq
    a1 = [g[i] * w[i] for i in range(n)]  # a1 = g^w
    a2 = [h[i] * w[i] for i in range(n)]  # a2 = h^w
    e = _DLEQ_derive_challenge(x, y, a1, a2)  # the challenge e
    z = [w[i] - (α[i] * e) for i in range(n)]  # the response(s) z
    return e, z[0] if n == 1 else z
Esempio n. 5
0
def test_dleq_non_equal():
    a = Scalar.random()
    b = Scalar.random()
    e, z = _DLEQ_prove(G, G * a, H, H * b, a)
    assert not _DLEQ_verify(G, G * a, H, H * b, e, z)
Esempio n. 6
0
def test_dleq_invalid_challenge():
    α = Scalar.random()
    e, z = _DLEQ_prove(G, G * α, H, H * α, α)
    e += Scalar(1)
    assert not _DLEQ_verify(G, G * α, H, H * α, e, z)
Esempio n. 7
0
def test_dleq():
    α = Scalar.random()
    e, z = _DLEQ_prove(G, G * α, H, H * α, α)
    assert _DLEQ_verify(G, G * α, H, H * α, e, z)
Esempio n. 8
0
def keygen():
    """ generates a fresh ed25519 keypair (sk, pk = h^sk) for a participant in the PVSS
    """
    secret_key = Scalar.random()
    public_key = H * secret_key
    return secret_key, public_key
Esempio n. 9
0
assert N == 128, "set i.e. N=128 before running this file in config.py"

keypairs = [KeyPair.random() for i in range(N - 1)]
public_keys = [k.public_key for k in keypairs]
shared_secret, encrypted_shares, proofs = pvss.share_random_secret(
    public_keys, T)
decrypted_shares = [
    pvss.decrypt_share(share, keypair.secret_scalar)
    for share, keypair in zip(encrypted_shares, keypairs)
]

dataset_header = DatasetHeader(
    round_idx=4711,
    prev_round_idx=4710,
    revealed_secret=Scalar.random(),
    beacon=Hash(utils.deterministic_random_bytes(32, "some beacon")),
    recovered_beacons=[],
    merkle_root=merkle.compute_root(
        [Hash(bytes(es)) for es in encrypted_shares]))

decryption_proofs = [
    pvss.prove_share_decryption(decrypted_share, encrypted_share,
                                keypair.secret_scalar, keypair.public_key)
    for decrypted_share, encrypted_share, keypair in zip(
        decrypted_shares, encrypted_shares, keypairs)
]
merkle_branches = [
    merkle.compute_branch([Hash(bytes(s.value))
                           for s in encrypted_shares], share_idx)
    for share_idx, _ in enumerate(encrypted_shares)
Esempio n. 10
0
def get(obj_type, num_elements=None, **kwargs):
    mapping = {
        Scalar: lambda: Scalar.random(),
        Point: lambda: Point.base_times(Scalar.random()),
        Hash: lambda: Hash(secrets.token_bytes(32)),
        Signature: lambda: Signature(secrets.token_bytes(64)),
        RecoveryCertificate:
            lambda: RecoveryCertificate(
                signers=random.sample(list(range(N)), F + 1),
                signatures=get(Signature, F + 1),
        ),
        ConfirmationCertificate:
            lambda: ConfirmationCertificate(
                dataset_header_digest=get(Hash),
                signers=random.sample(list(range(N)), F + 1),
                signatures=get(Signature, F + 1),
        ),
        ShareCorrectnessProof:
            lambda: ShareCorrectnessProof(
                commitments=get(Point, N - 1),
                challenge=get(Scalar),
                responses=get(Scalar, N - 1),
        ),
        ShareDecryptionProof:
            lambda: ShareDecryptionProof(
                challenge=get(Scalar),
                response=get(Scalar),
        ),
        RecoveredShare:
            lambda: RecoveredShare(
                share=get(Point),
                proof=get(ShareDecryptionProof),
                merkle_branch=get(Hash, merkle.branch_length(N - 1)),
        ),
        DatasetHeader:
            lambda **kws: DatasetHeader(
                round_idx=kws['round_idx'],
                prev_round_idx=kws['prev_round_idx'],
                revealed_secret=get(Scalar),
                beacon=get(Hash),
                recovered_beacons=get(Hash, kws['round_idx'] - kws['prev_round_idx'] - 1),
                merkle_root=get(Hash),
        ),
        Dataset:
            lambda **kws: Dataset(
                round_idx=kws['round_idx'],
                prev_round_idx=kws['prev_round_idx'],
                revealed_secret=get(Scalar),
                beacon=get(Hash),
                recovered_beacons=get(Hash, kws['round_idx'] - kws['prev_round_idx'] - 1),
                merkle_root=get(Hash),
                encrypted_shares=get(Point, N - 1),
                proof=get(ShareCorrectnessProof),
                confirmation_certificate=None if kws['prev_round_idx'] == 0 else get(ConfirmationCertificate),
                recovery_certificates=get(RecoveryCertificate, kws['round_idx'] - kws['prev_round_idx'] - 1),
        ),
        ProposeMessage:
            lambda **kws: ProposeMessage(
                sender=random.randint(0, N - 1),
                dataset=get(Dataset, **kws),
                dataset_header_signature=get(Signature),
                confirmation_certificate_signature=get(Signature),
        ),
        AcknowledgeMessage:
            lambda **kws: AcknowledgeMessage(
                sender=random.randint(0, N - 1),
                dataset_header=get(DatasetHeader, **kws),
                dataset_header_signature=get(Signature),
        ),
        ConfirmMessage:
            lambda **kws: ConfirmMessage(
                sender=random.randint(0, N - 1),
                round_idx=kws.get('round_idx', random.randint(0, 1000_000)),
                dataset_header_digest=get(Hash),
        ),
        RecoverMessage:
            lambda **kws: RecoverMessage(
                sender=random.randint(0, N - 1),
                round_idx=kws.get('round_idx', random.randint(0, 1000_000)),
                recovery_certificate_signature=get(Signature),
                recovered_share=get(RecoveredShare) if kws.get('add_recovered_share', True) else None
        ),
        SignedMessage:
            lambda **kws: SignedMessage(
                message=get(kws['msg_type'], **kws),
                signature=get(Signature),
        )
    }
    if num_elements is None:
        return mapping[obj_type](**kwargs)
    return [mapping[obj_type](**kwargs) for _ in range(num_elements)]