示例#1
0
def load_config(n=None):
    if n is None:
        n = N

    from hydrand import merkle
    from hydrand.data import ShareCorrectnessProof, NodeInfo

    CONFIG_DIR = os.path.join(CONFIG_BASE_DIR, f"{n:03}")
    if not os.path.exists(CONFIG_DIR):
        assert NETWORK_CONFIG != "amazon", "do never generate config on the fly for amazon tests"
        logging.warning("config does not exist, generating one on the fly")
        return generate_sample_config()

    addresses, ports = load_network_config()
    node_infos = []
    for node_id in range(n):
        if MODE == "testing" or NODE_ID == node_id:
            with open(os.path.join(CONFIG_DIR, f"{node_id:03}.secret_key"),
                      "rb") as f:
                keypair = KeyPair(f.read())
            public_key = keypair.public_key
            with open(os.path.join(CONFIG_DIR, f"{node_id:03}.initial_secret"),
                      "rb") as f:
                initial_secret = Scalar.from_bytes(f.read())
        else:
            keypair = None
            initial_secret = None
            with open(os.path.join(CONFIG_DIR, f"{node_id:03}.public_key"),
                      "rb") as f:
                public_key = Point.from_bytes(f.read())

        with open(
                os.path.join(CONFIG_DIR, f"{node_id:03}.initial_pvss_shares"),
                "rb") as f:
            shares = [Point.from_bytes(f.read(32)) for i in range(n - 1)]
        with open(os.path.join(CONFIG_DIR, f"{node_id:03}.initial_pvss_proof"),
                  "rb") as f:
            proof = ShareCorrectnessProof(
                commitments=[
                    Point.from_bytes(f.read(32)) for i in range(n - 1)
                ],
                challenge=Scalar.from_bytes(f.read(32)),
                responses=[
                    Scalar.from_bytes(f.read(32)) for i in range(n - 1)
                ],
            )

        merkle_root = merkle.compute_root(
            [merkle.Hash(bytes(es)) for es in shares])
        node_infos.append(
            NodeInfo(node_id, addresses[node_id], ports[node_id], keypair,
                     public_key, initial_secret, shares, proof, merkle_root))
    return node_infos
示例#2
0
    def process_recover(self, msg: RecoverMessage):
        if self.recovery_certificate and self.beacon:
            return

        if not self.verify_recovery_certificate_signature(
            msg.recovery_certificate_signature, NODE_INFOS[msg.sender].public_key
        ):
            self.flag_adversary(msg.sender)
            return

        self.recover_messages[msg.sender] = msg
        if len(self.recover_messages) == F + 1:
            self.create_recovery_certificate()

        rs = msg.recovered_share
        if rs:
            root_hash = self.lookup_merkle_root()
            share_idx = msg.sender if msg.sender < self.leader else msg.sender - 1
            enc_share = Point.from_bytes(merkle.get_leaf(rs.merkle_branch, share_idx, N - 1))

            # lookup dataset (header) for the leader
            # at least a header does exists
            if not merkle.verify_branch(rs.merkle_branch, root_hash, share_idx, N - 1):  # type: ignore
                return

            if not pvss.verify_decrypted_share(rs.share, enc_share, NODE_INFOS[msg.sender].public_key, rs.proof):
                self.flag_adversary(msg.sender)
                return

            self.shares_for_recovery[msg.sender] = rs.share
            self.logger.info("storing share for recovery, now %d shares in total", len(self.shares_for_recovery))

            if len(self.shares_for_recovery) == F + 1:
                secret = self.recover_shared_secret()
                self.compute_beacon(recovered_secret=secret)
        else:
            self.logger.warning("RECOVER MESSAGE DID NOT INCLUDE A SHARE")
示例#3
0
""" implementation of the publicly-verifiable secret sharing protocol described in Scrape
    we use the DDH variant from page 12 of the Scrape paper
    see: https://eprint.iacr.org/2017/216.pdf
"""

import hashlib
from copy import copy
from typing import List, Optional, Tuple

from hydrand.data import ShareCorrectnessProof, ShareDecryptionProof
from hydrand.ed25519 import Point, Scalar, GROUP_ORDER

# initialize two independent generator points g, and h
G = Point.from_uniform(hashlib.sha256(bytes(Point.B)).digest())
H = Point.B


class Polynomial:
    def __init__(self, coeffs: List[Scalar]):
        self.coeffs = coeffs

    def __call__(self, arg: int) -> Scalar:
        x = Scalar(arg)
        result = self.coeffs[0] + (self.coeffs[1] * x)
        x_pow = copy(x)
        for i in range(2, len(self.coeffs)):
            x_pow *= x
            result += self.coeffs[i] * x_pow
        return result

    @staticmethod
示例#4
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)]
示例#5
0
def test_from_uniform():
    digest = hashlib.sha256(b"some stuff").digest()
    p = Point.from_uniform(digest)
    assert p.is_valid()
示例#6
0
def test_neg_base_point():
    Bneg = Point(fe.recover_x(B.y, sign=1), B.y)
    assert Bneg != B
    assert Bneg.x != B.x
    assert Bneg.y == B.y
    assert Bneg.sign != B.sign
示例#7
0
def test_base_times_zero_fails():
    with pytest.raises(ValueError):
        Point.base_times(Scalar(0))
示例#8
0
def test_base_multiply_by_one():
    assert B == Point.base_times(Scalar(1))