Esempio n. 1
0
    def connect(self,
                name=None,
                remoteId=None,
                ha=None,
                verKeyRaw=None,
                publicKeyRaw=None):
        """
        Connect to the node specified by name.
        """
        if not name:
            raise ValueError('Remote name should be specified')

        if name in self.remotes:
            remote = self.remotes[name]
        else:
            publicKey = z85.encode(publicKeyRaw) if publicKeyRaw else self.getPublicKey(name)
            verKey = z85.encode(verKeyRaw) if verKeyRaw else self.getVerKey(name)
            if not ha or not publicKey or (self.isRestricted and not verKey):
                raise ValueError('{} doesnt have enough info to connect. '
                                 'Need ha, public key and verkey. {} {} {}'.
                                 format(name, ha, verKey, publicKey))
            remote = self.addRemote(name, ha, verKey, publicKey)

        public, secret = self.selfEncKeys
        remote.connect(self.ctx, public, secret)

        logger.info("{} looking for {} at {}:{}".
                    format(self, name or remote.name, *remote.ha),
                    extra={"cli": "PLAIN", "tags": ["node-looking"]})

        # This should be scheduled as an async task
        self.sendPingPong(remote, is_ping=True)
        return remote.uid
    def generate(self):
        verif_key, sig_key = crypto_sign_seed_keypair(self.seed)
        public_key, secret_key = ep2c(verif_key), es2c(sig_key)

        public_key_file = self.cert_file_from_key(public_key=z85.encode(public_key).decode("utf-8"), private_key=None)
        private_key_file = self.cert_file_from_key(public_key=z85.encode(public_key).decode("utf-8"), private_key=z85.encode(secret_key).decode("utf-8"))
        verif_key_file = self.cert_file_from_key(public_key=z85.encode(verif_key).decode("utf-8"), private_key=None)
        sig_key_file = self.cert_file_from_key(public_key=z85.encode(verif_key).decode("utf-8"), private_key=z85.encode(sig_key[:32]).decode("utf-8"))

        public_key = base58.b58encode(public_key).decode("utf-8")
        verif_key = base58.b58encode(verif_key).decode("utf-8")

        sk, pk, key_proof = self.bls_generator.generate()
        bls = Bls(pk=pk, sk=sk, key_pop=key_proof)

        node = Crypto(name=self.identity_name, public_key=public_key, public_key_file=public_key_file,
                      secret_key=secret_key, secret_key_file=private_key_file,
                      sig_key=sig_key, sig_key_file=sig_key_file,
                      verif_key=verif_key, verif_key_file=verif_key_file,
                      bls_keys=bls, is_client=False)

        client = Crypto(name=self.identity_name, public_key=public_key, public_key_file=public_key_file,
                        secret_key=secret_key, secret_key_file=private_key_file,
                        sig_key=sig_key, sig_key_file=sig_key_file,
                        verif_key=verif_key, verif_key_file=verif_key_file,
                        bls_keys=bls, is_client=True)

        return Identity(
            name=self.identity_name, vault_path=self.vault_path, node=node, client=client, did=self.did, seed=self.seed
        )
Esempio n. 3
0
 def to_json(self, redact=True):
     """
     Output the current node details in json
     @return JSON style dictionary
     """
     data = {'node_id': z85.encode(self.node_id),
             'address': self.address,
             'port': self.port,
             'hostname': self.hostname,
             'discovered': self.discovered,
             'first_contact': self.first_contact,
             'last_contact': self.last_contact,
             'last_failure': self.last_failure,
             'latency_ms': self.latency,
             'msg_loss': self.msg_loss, 
             'failures': self.failures,
             'queries_in': self.queries_in,
             'queries_out': self.queries_out,
             'responses_in': self.responses_in,
             'responses_out': self.responses_out,
             'status': self.state,
             }
     if not redact and self.secret_key:
         data.update['secret_key'] = z85.encode(self.secret_key)
     return data
Esempio n. 4
0
 def to_json(self, redact=True):
     """
     Output the current node details in json
     @return JSON style dictionary
     """
     data = {
         'node_id': z85.encode(self.node_id),
         'address': self.address,
         'port': self.port,
         'hostname': self.hostname,
         'discovered': self.discovered,
         'first_contact': self.first_contact,
         'last_contact': self.last_contact,
         'last_failure': self.last_failure,
         'latency_ms': self.latency,
         'msg_loss': self.msg_loss,
         'failures': self.failures,
         'queries_in': self.queries_in,
         'queries_out': self.queries_out,
         'responses_in': self.responses_in,
         'responses_out': self.responses_out,
         'status': self.state,
     }
     if not redact and self.secret_key:
         data.update['secret_key'] = z85.encode(self.secret_key)
     return data
Esempio n. 5
0
 def connectTo(self, ha, verkey, pubkey):
     if not self.isConnectedTo(ha=ha):
         assert pubkey, 'Need public key to connect to {}'.format(ha)
         zvk = z85.encode(friendlyToRaw(verkey)) if verkey else None
         zpk = z85.encode(friendlyToRaw(pubkey))
         self.connect(name=verkey or pubkey, ha=ha, verKey=zvk, publicKey=zpk)
     else:
         logger.debug('{} already connected {}'.format(self, ha))
Esempio n. 6
0
    def _authenticate_curve(self, domain, client_key):
        """CURVE ZAP authentication"""
        allowed = False
        reason = b""
        if self.allow_any:
            allowed = True
            reason = b"OK"
            self.log.debug("ALLOWED (CURVE allow any client)")
        elif self.credentials_providers != {}:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.credentials_providers:
                z85_client_key = z85.encode(client_key)
                # Callback to check if key is Allowed
                if (self.credentials_providers[domain].callback(
                        domain, z85_client_key)):
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug(
                    "%s (CURVE auth_callback) domain=%s client_key=%s",
                    status,
                    domain,
                    z85_client_key,
                )
            else:
                reason = b"Unknown domain"
        else:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.certs:
                # The certs dict stores keys in z85 format, convert binary key to z85 bytes
                z85_client_key = z85.encode(client_key)
                if self.certs[domain].get(z85_client_key):
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug(
                    "%s (CURVE) domain=%s client_key=%s",
                    status,
                    domain,
                    z85_client_key,
                )
            else:
                reason = b"Unknown domain"

        return allowed, reason
Esempio n. 7
0
def encode(data):
    data_bin = bytes(data)
    while len(data_bin) % 4:
        data_bin = data_bin + "\0"
    if verbose:
        print "Encoding {" + data_bin + "} (total " + str(len(data_bin)) + " bytes)"
        print z85.encode(data_bin)
    else:
        sys.stdout.write(z85.encode(data_bin))
Esempio n. 8
0
    def __init__(self, signing_key, witness_list, url, sbb_index):
        self.log = get_logger("SubBlockBuilder_{}".format(sb_index))
        # Comment out below for more granularity in debugging
        # self.log.setLevel(logging.INFO)

        #self.log.important("SubBlockBuilder started with url {}".format(url))

        # Register signal handler to teardown
        signal.signal(signal.SIGTERM, self._signal_teardown)

        # need to revisit this when threading strategy is clear
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        self.signing_key = signing_key
        # witness_list should be comma separated list of ip:vk  
        self.witness_table = self._parse_witness_list(witness_list)
        self.url = url
        self.sbb_index = sbb_index
        self.block_num = (int) sbb_index / 16       # hard code this for now
        self.sub_block_num = (int) sb_index % 16
        self.num_txs = 0
        self.num_sub_blocks = 0
        self.tasks = []

        #SenecaInterpreter connect with BlockManager (parent process that spawned this one)
        self.context = zmq.asyncio.Context()
        self.socket = self.context.socket(zmq.PAIR)  # For communication with main process
        self.socket.connect(self.url)

        # do we need this still? or do we move it to a util methods
        self.verifying_key = wallet.get_vk(self.signing_key)
        skg = SigningKey(seed=bytes.fromhex(sk))
        self.vk = skg.verify_key.encode().hex()
        self.public_key = self.vk2pk(self.vk)
        self.private_key = crypto_sign_ed25519_sk_to_curve25519(skg._signing_key).hex()
        priv = PrivateKey(bytes.fromhex(self.private_key))
        publ = priv.public_key
        self.public_key = public_key = encode(publ._public_key)
        self.secret = secret_key = encode(priv._private_key)

        self.pending_txs = LinkedHashTable()
        self.interpreter = SenecaInterpreter()
        self._recently_seen = CappedSet(max_size=DUPE_TABLE_SIZE)

        try:
            self._subscribe_to_witnesses()
            # start event loop and start listening witness sockets as well as mgr
            self.run_loop_second_time()
        except Exception as e:
            err_msg = '\n' + '!' * 64 + '\nSBB terminating with exception:\n' + str(traceback.format_exc())
            err_msg += '\n' + '!' * 64 + '\n'
            self.log.error(err_msg)
        finally:
            self._teardown()
Esempio n. 9
0
def genkeys(sk_hex):
    sk = SigningKey(seed=bytes.fromhex(sk_hex))
    vk = sk.verify_key.encode().hex()
    public_key = VerifyKey(bytes.fromhex(vk)).to_curve25519_public_key()._public_key
    private_key = crypto_sign_ed25519_sk_to_curve25519(sk._signing_key)
    return {
        'sk': sk_hex,
        'vk': vk,
        'public_key': public_key.hex(),
        'private_key': encode(private_key),
        'curve_key': encode(public_key)
    }
Esempio n. 10
0
def createEncAndSigKeys(enc_key_dir, sig_key_dir, name, seed=None):
    seed = seed or randomSeed()
    if isinstance(seed, str):
        seed = seed.encode()
    # ATTENTION: Passing `seed` encoded to bytes or not in
    # `crypto_sign_seed_keypair` will generate different keypairs
    verif_key, sig_key = crypto_sign_seed_keypair(seed)
    createCertsFromKeys(sig_key_dir, name, z85.encode(verif_key),
                        z85.encode(sig_key[:32]))
    public_key, secret_key = ep2c(verif_key), es2c(sig_key)
    createCertsFromKeys(enc_key_dir, name, z85.encode(public_key),
                        z85.encode(secret_key))
    return (public_key, secret_key), (verif_key, sig_key)
Esempio n. 11
0
    def initRemoteKeys(name, remoteName, baseDir, verkey, override=False):
        homeDir = ZStack.homeDirPath(baseDir, name)
        verifDirPath = ZStack.verifDirPath(homeDir)
        pubDirPath = ZStack.publicDirPath(homeDir)
        for d in (homeDir, verifDirPath, pubDirPath):
            os.makedirs(d, exist_ok=True)

        if isHex(verkey):
            verkey = unhexlify(verkey)

        createCertsFromKeys(verifDirPath, remoteName, z85.encode(verkey))
        public_key = ed25519PkToCurve25519(verkey)
        createCertsFromKeys(pubDirPath, remoteName, z85.encode(public_key))
Esempio n. 12
0
    def initRemoteKeys(name, remoteName, baseDir, verkey, override=False):
        homeDir = ZStack.homeDirPath(baseDir, name)
        verifDirPath = ZStack.verifDirPath(homeDir)
        pubDirPath = ZStack.publicDirPath(homeDir)
        for d in (homeDir, verifDirPath, pubDirPath):
            os.makedirs(d, exist_ok=True)

        if isHex(verkey):
            verkey = unhexlify(verkey)

        createCertsFromKeys(verifDirPath, remoteName, z85.encode(verkey))
        public_key = ed25519PkToCurve25519(verkey)
        createCertsFromKeys(pubDirPath, remoteName, z85.encode(public_key))
Esempio n. 13
0
    def __init__(self, seed=None):
        if isinstance(seed, str):
            seed = bytes.fromhex(seed)

        if seed is None:
            seed = secrets.token_bytes(32)

        self.sk = nacl.signing.SigningKey(seed=seed)
        self.vk = self.sk.verify_key

        self.curve_sk = z85.encode(
            self.sk.to_curve25519_private_key().encode())
        self.curve_vk = z85.encode(self.vk.to_curve25519_public_key().encode())
Esempio n. 14
0
def createEncAndSigKeys(enc_key_dir, sig_key_dir, name, seed=None):
    seed = seed or randomSeed()
    if isinstance(seed, str):
        seed = seed.encode()
    # ATTENTION: Passing `seed` encoded to bytes or not in
    # `crypto_sign_seed_keypair` will generate different keypairs
    verif_key, sig_key = crypto_sign_seed_keypair(seed)
    createCertsFromKeys(sig_key_dir, name, z85.encode(verif_key),
                        z85.encode(sig_key[:32]))
    public_key, secret_key = ep2c(verif_key), es2c(sig_key)
    createCertsFromKeys(enc_key_dir, name, z85.encode(public_key),
                        z85.encode(secret_key))
    return (public_key, secret_key), (verif_key, sig_key)
Esempio n. 15
0
    def connect(self,
                name=None,
                remoteId=None,
                ha=None,
                verKeyRaw=None,
                publicKeyRaw=None):
        """
        Connect to the node specified by name.
        """
        if not name:
            raise ValueError('Remote name should be specified')

        publicKey = None
        if name in self.remotes:
            remote = self.remotes[name]
        else:
            publicKey = z85.encode(
                publicKeyRaw) if publicKeyRaw else self.getPublicKey(name)
            verKey = z85.encode(verKeyRaw) if verKeyRaw else self.getVerKey(
                name)
            if not ha or not publicKey or (self.isRestricted and not verKey):
                raise ValueError(
                    '{} doesnt have enough info to connect. '
                    'Need ha, public key and verkey. {} {} {}'.format(
                        name, ha, verKey, publicKey))
            remote = self.addRemote(name, ha, verKey, publicKey)

        public, secret = self.selfEncKeys
        remote.connect(self.ctx, public, secret)

        logger.info("{}{} looking for {} at {}:{}".format(
            CONNECTION_PREFIX, self, name or remote.name, *remote.ha),
                    extra={
                        "cli": "PLAIN",
                        "tags": ["node-looking"]
                    })

        # This should be scheduled as an async task

        self.sendPingPong(remote, is_ping=True)

        # re-send previously stashed pings/pongs from unknown remotes
        logger.trace("{} stashed pongs: {}".format(self.name,
                                                   str(self._stashed_pongs)))
        if publicKey in self._stashed_pongs:
            logger.trace("{} sending stashed pongs to {}".format(
                self.name, str(publicKey)))
            self._stashed_pongs.discard(publicKey)
            self.sendPingPong(name, is_ping=False)

        return remote.uid
Esempio n. 16
0
File: base.py Progetto: zeromq/pyzmq
    def _authenticate_curve(self, domain, client_key):
        """CURVE ZAP authentication"""
        allowed = False
        reason = b""
        if self.allow_any:
            allowed = True
            reason = b"OK"
            self.log.debug("ALLOWED (CURVE allow any client)")
        elif self.credentials_providers != {}:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.credentials_providers:
                z85_client_key = z85.encode(client_key)
                # Callback to check if key is Allowed
                if (self.credentials_providers[domain].callback(domain, z85_client_key)):
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug("%s (CURVE auth_callback) domain=%s client_key=%s",
                    status, domain, z85_client_key,
                )
            else:
                reason = b"Unknown domain"
        else:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.certs:
                # The certs dict stores keys in z85 format, convert binary key to z85 bytes
                z85_client_key = z85.encode(client_key)
                if self.certs[domain].get(z85_client_key):
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug("%s (CURVE) domain=%s client_key=%s",
                    status, domain, z85_client_key,
                )
            else:
                reason = b"Unknown domain"

        return allowed, reason
Esempio n. 17
0
    def create_from_private_key(cls, private_key):
        priv = PrivateKey(bytes.fromhex(private_key))
        publ = priv.public_key
        public_key = encode(publ._public_key)
        secret = encode(priv._private_key)

        base_filename = join(cls.keys_dir, cls.keyname)
        public_key_file = "{0}.key".format(base_filename)
        now = datetime.datetime.now()

        zmq.auth.certs._write_key_file(
            public_key_file, zmq.auth.certs._cert_public_banner.format(now),
            public_key)

        return public_key, secret
Esempio n. 18
0
async def test_trusted_curve_with_wrong_peer_public_key(
        loop, unused_tcp_port_factory):
    from pseud import Client, Server
    from pseud.utils import register_rpc
    server_id = b'server'
    port = unused_tcp_port_factory()
    endpoint = f'tcp://127.0.0.1:{port}'
    server_public, server_secret = zmq.curve_keypair()

    server = Server(server_id, security_plugin='trusted_curve',
                    public_key=server_public,
                    secret_key=server_secret,
                    loop=loop)
    server.bind(endpoint)

    alice_public, alice_secret = \
        server.auth_backend.known_identities[b'alice']
    client = Client(server_id,
                    user_id=b'alice',
                    security_plugin='trusted_curve',
                    public_key=alice_public,
                    secret_key=alice_secret,
                    peer_public_key=z85.encode(b'R' * 32),
                    timeout=.5,
                    loop=loop)
    client.connect(endpoint)
    assert server.socket.mechanism == zmq.CURVE
    assert client.socket.mechanism == zmq.CURVE

    register_rpc(name='string.lower')(str.lower)

    async with server, client:
        with pytest.raises(asyncio.TimeoutError):
            await client.string.lower('BAR')
Esempio n. 19
0
 def __str__(self):
     """
     @return: Brief string representation of this node.
     """
     return '{0}:{1} - {2} ({3})'.format(self.address, self.port,
                                         z85.encode(self.node_id),
                                         self.hostname)
Esempio n. 20
0
 def __str__(self):
     """
     @return: Brief string representation of this node.
     """
     return '{0}:{1} - {2} ({3})'.format(self.address, self.port,
                                         z85.encode(self.node_id),
                                         self.hostname)
Esempio n. 21
0
    def _authenticate_curve(self, domain, client_key):
        """CURVE ZAP authentication"""
        allowed = False
        reason = b""
        if self.allow_any:
            allowed = True
            reason = b"OK"
            self.log.debug("ALLOWED (CURVE allow any client)")
        else:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.certs:
                # The certs dict stores keys in z85 format, convert binary key to z85 bytes
                z85_client_key = z85.encode(client_key)
                if z85_client_key in self.certs[domain] or self.certs[domain] == b'OK':
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug("%s (CURVE) domain=%s client_key=%s",
                    status, domain, z85_client_key,
                )
            else:
                reason = b"Unknown domain"

        return allowed, reason
Esempio n. 22
0
async def test_trusted_curve_with_wrong_peer_public_key(
        loop, unused_tcp_port_factory):
    from pseud import Client, Server
    from pseud.utils import register_rpc
    server_id = b'server'
    port = unused_tcp_port_factory()
    endpoint = f'tcp://127.0.0.1:{port}'
    server_public, server_secret = zmq.curve_keypair()

    server = Server(server_id, security_plugin='trusted_curve',
                    public_key=server_public,
                    secret_key=server_secret,
                    loop=loop)
    server.bind(endpoint)

    alice_public, alice_secret = \
        server.auth_backend.known_identities[b'alice']
    client = Client(server_id,
                    user_id=b'alice',
                    security_plugin='trusted_curve',
                    public_key=alice_public,
                    secret_key=alice_secret,
                    peer_public_key=z85.encode(b'R' * 32),
                    timeout=.5,
                    loop=loop)
    client.connect(endpoint)
    assert server.socket.mechanism == zmq.CURVE
    assert client.socket.mechanism == zmq.CURVE

    register_rpc(name='string.lower')(str.lower)

    async with server, client:
        with pytest.raises(asyncio.TimeoutError):
            await client.string.lower('BAR')
Esempio n. 23
0
def test_trusted_curve_with_wrong_peer_public_key():
    from pseud._gevent import Client, Server
    server_id = 'server'
    endpoint = 'inproc://{}'.format(__name__)
    endpoint = 'tcp://127.0.0.1:8998'
    server_public, server_secret = zmq.curve_keypair()
    client_public, client_secret = zmq.curve_keypair()
    client = Client(server_id,
                    security_plugin='trusted_curve',
                    public_key=client_public,
                    secret_key=client_secret,
                    peer_public_key=z85.encode('R' * 32))

    server = Server(server_id,
                    security_plugin='trusted_curve',
                    public_key=server_public,
                    secret_key=server_secret)

    server.bind(endpoint)
    client.connect(endpoint)
    assert server.socket.mechanism == zmq.CURVE
    assert client.socket.mechanism == zmq.CURVE

    server.start()
    future = client.string.lower('BAR')
    with pytest.raises(Timeout):
        future.get(timeout=0.1)
    server.stop()
    client.stop()
Esempio n. 24
0
    def _authenticate_curve(self, domain, client_key):
        """CURVE ZAP authentication"""
        allowed = False
        reason = b""
        if self.allow_any:
            allowed = True
            reason = b"OK"
            self.log.debug("ALLOWED (CURVE allow any client)")
        else:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.certs:
                # The certs dict stores keys in z85 format, convert binary key to z85 bytes
                z85_client_key = z85.encode(client_key)
                if z85_client_key in self.certs[domain] or self.certs[
                        domain] == b'OK':
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "ALLOWED" if allowed else "DENIED"
                self.log.debug(
                    "%s (CURVE) domain=%s client_key=%s",
                    status,
                    domain,
                    z85_client_key,
                )
            else:
                reason = b"Unknown domain"

        return allowed, reason
Esempio n. 25
0
 def test_generate_from_public_key(self):
     self.ironhouse.create_from_public_key(encode(self.public_key.encode()))
     self.assertTrue(listdir(self.ironhouse.public_keys_dir),
                     'public keys dir not created')
     self.assertTrue(
         exists('{}/ironhouse.key'.format(self.ironhouse.public_keys_dir)),
         'public key not generated')
Esempio n. 26
0
def test_trusted_curve_with_wrong_peer_public_key():
    from pseud._gevent import Client, Server
    server_id = 'server'
    endpoint = 'inproc://{}'.format(__name__)
    endpoint = 'tcp://127.0.0.1:8998'
    server_public, server_secret = zmq.curve_keypair()
    client_public, client_secret = zmq.curve_keypair()
    client = Client(server_id,
                    security_plugin='trusted_curve',
                    public_key=client_public,
                    secret_key=client_secret,
                    peer_public_key=z85.encode('R' * 32))

    server = Server(server_id, security_plugin='trusted_curve',
                    public_key=server_public,
                    secret_key=server_secret)

    server.bind(endpoint)
    client.connect(endpoint)
    assert server.socket.mechanism == zmq.CURVE
    assert client.socket.mechanism == zmq.CURVE

    server.start()
    future = client.string.lower('BAR')
    with pytest.raises(Timeout):
        future.get(timeout=0.1)
    server.stop()
    client.stop()
Esempio n. 27
0
    def _authenticate_curve(self, domain, client_key):
        '''
        Perform ZAP authentication check for CURVE mechanism
        '''
        allowed = False
        reason = b""
        if self.allow_any:
            allowed = True
            reason = b"OK"
            logging.debug("ALLOWED (CURVE allow any client)")
        else:
            # If no explicit domain is specified then use the default domain
            if not domain:
                domain = '*'

            if domain in self.certs:
                # The certs dict stores keys in z85 format, convert binary key to z85 bytes
                z85_client_key = z85.encode(client_key)
                if z85_client_key in self.certs[domain]:
                    allowed = True
                    reason = b"OK"
                else:
                    reason = b"Unknown key"

                status = "DENIED"
                if allowed:
                    status = "ALLOWED"
                logging.debug("{0} (CURVE) domain={1} client_key={2}".format(status,
                    domain, z85_client_key))
            else:
                reason = b"Unknown domain"

        return allowed, reason
Esempio n. 28
0
    def connect(self,
                name=None,
                remoteId=None,
                ha=None,
                verKeyRaw=None,
                publicKeyRaw=None):
        """
        Connect to the node specified by name.
        """
        if not name:
            raise ValueError('Remote name should be specified')

        publicKey = None
        if name in self.remotes:
            remote = self.remotes[name]
        else:
            publicKey = z85.encode(
                publicKeyRaw) if publicKeyRaw else self.getPublicKey(name)
            verKey = z85.encode(
                verKeyRaw) if verKeyRaw else self.getVerKey(name)
            if not ha or not publicKey or (self.isRestricted and not verKey):
                raise ValueError('{} doesnt have enough info to connect. '
                                 'Need ha, public key and verkey. {} {} {}'.
                                 format(name, ha, verKey, publicKey))
            remote = self.addRemote(name, ha, verKey, publicKey)

        public, secret = self.selfEncKeys
        remote.connect(self.ctx, public, secret)

        logger.info("{}{} looking for {} at {}:{}"
                    .format(CONNECTION_PREFIX, self,
                            name or remote.name, *remote.ha),
                    extra={"cli": "PLAIN", "tags": ["node-looking"]})

        # This should be scheduled as an async task

        self.sendPingPong(remote, is_ping=True)

        # re-send previously stashed pings/pongs from unknown remotes
        logger.trace("{} stashed pongs: {}".format(self.name, str(self._stashed_pongs)))
        if publicKey in self._stashed_pongs:
            logger.trace("{} sending stashed pongs to {}".format(self.name, str(z85_to_friendly(publicKey))))
            self._stashed_pongs.discard(publicKey)
            self.sendPingPong(name, is_ping=False)

        return remote.uid
Esempio n. 29
0
def _generate_coupon():
    """
    Generate coupon using current month/year
    :return: 
    """
    now = datetime.datetime.now()
    month = now.strftime('%b').upper()
    year = now.strftime('%y')
    return z85.encode('{month}{year}-99'.format(month=month, year=year))
Esempio n. 30
0
def id_for_key(key):
    """
    Given an object key, map this to a node id for storage.
    @param key: String key for storing an object.
    @return: node_id of a target node for the given key.
    """
    hasher = hashlib.sha256()
    hasher.update(key)
    return z85.encode(hasher.digest())
Esempio n. 31
0
def decode_key(key):
    '''Parse and return a Z85 encoded key from other encodings.'''
    length = len(key)
    if length == 40:
        return key
    elif length == 43:
        return z85.encode(base64.urlsafe_b64decode(key + '='))
    elif length == 44:
        return z85.encode(base64.urlsafe_b64decode(key))
    elif length == 54:
        return base64.urlsafe_b64decode(key + '==')
    elif length == 56:
        return base64.urlsafe_b64decode(key)
    elif length == 64:
        return z85.encode(binascii.unhexlify(key))
    elif length == 80:
        return binascii.unhexlify(key)
    raise ValueError('unknown key encoding')
Esempio n. 32
0
def decode_key(key):
    '''Parse and return a Z85 encoded key from other encodings.'''
    length = len(key)
    if length == 40:
        return key
    elif length == 43:
        return z85.encode(base64.urlsafe_b64decode(key + '='))
    elif length == 44:
        return z85.encode(base64.urlsafe_b64decode(key))
    elif length == 54:
        return base64.urlsafe_b64decode(key + '==')
    elif length == 56:
        return base64.urlsafe_b64decode(key)
    elif length == 64:
        return z85.encode(binascii.unhexlify(key))
    elif length == 80:
        return binascii.unhexlify(key)
    raise ValueError('unknown key encoding')
Esempio n. 33
0
    def connect(self, name=None, remoteId=None, ha=None, verKeyRaw=None, publicKeyRaw=None):
        """
        Connect to the node specified by name.
        """
        if not name:
            raise ValueError('Name needs to be specified')
        if name not in self.remotes:
            publicKey = None
            if not publicKeyRaw:
                try:
                    publicKey = self.getPublicKey(name)
                except KeyError:
                    raise PublicKeyNotFoundOnDisk(self.name, name)
            else:
                publicKey = z85.encode(publicKeyRaw)

            verKey = None
            if not verKeyRaw:
                try:
                    verKey = self.getVerKey(name)
                except KeyError:
                    if self.isRestricted:
                        raise VerKeyNotFoundOnDisk(self.name, name)
            else:
                verKey = z85.encode(verKeyRaw)

            if not (ha and publicKey and (not self.isRestricted or verKey)):
                raise ValueError('{} doesnt have enough info to connect. '
                                 'Need ha, public key and verkey. {} {} {}'.
                                 format(name, ha, verKey, publicKey))
            remote = self.addRemote(name, ha, verKey, publicKey)
        else:
            remote = self.remotes[name]

        public, secret = self.selfEncKeys
        remote.connect(self.ctx, public, secret)

        logger.info("{} looking for {} at {}:{}".
                    format(self, name or remote.name, *remote.ha),
                    extra={"cli": "PLAIN", "tags": ["node-looking"]})

        # This should be scheduled as an async task
        self.sendPing(remote)
        return remote.uid
Esempio n. 34
0
    def test_client_secret(self):
        client_secret = (b"\x7B\xB8\x64\xB4\x89\xAF\xA3\x67"
                         b"\x1F\xBE\x69\x10\x1F\x94\xB3\x89"
                         b"\x72\xF2\x48\x16\xDF\xB0\x1B\x51"
                         b"\x65\x6B\x3F\xEC\x8D\xFD\x08\x88")
        encoded = z85.encode(client_secret)

        self.assertEqual(encoded, b"D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs")
        decoded = z85.decode(encoded)
        self.assertEqual(decoded, client_secret)
Esempio n. 35
0
    def test_server_secret(self):
        server_secret = (b"\x8E\x0B\xDD\x69\x76\x28\xB9\x1D"
                         b"\x8F\x24\x55\x87\xEE\x95\xC5\xB0"
                         b"\x4D\x48\x96\x3F\x79\x25\x98\x77"
                         b"\xB4\x9C\xD9\x06\x3A\xEA\xD3\xB7")
        encoded = z85.encode(server_secret)

        self.assertEqual(encoded, b"JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6")
        decoded = z85.decode(encoded)
        self.assertEqual(decoded, server_secret)
Esempio n. 36
0
    def test_client_public(self):
        client_public = (b"\xBB\x88\x47\x1D\x65\xE2\x65\x9B"
                         b"\x30\xC5\x5A\x53\x21\xCE\xBB\x5A"
                         b"\xAB\x2B\x70\xA3\x98\x64\x5C\x26"
                         b"\xDC\xA2\xB2\xFC\xB4\x3F\xC5\x18")
        encoded = z85.encode(client_public)

        self.assertEqual(encoded, b"Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID")
        decoded = z85.decode(encoded)
        self.assertEqual(decoded, client_public)
Esempio n. 37
0
    def test_server_public(self):
        server_public = (b"\x54\xFC\xBA\x24\xE9\x32\x49\x96"
                         b"\x93\x16\xFB\x61\x7C\x87\x2B\xB0"
                         b"\xC1\xD1\xFF\x14\x80\x04\x27\xC5"
                         b"\x94\xCB\xFA\xCF\x1B\xC2\xD6\x52")
        encoded = z85.encode(server_public)

        self.assertEqual(encoded, b"rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7")
        decoded = z85.decode(encoded)
        self.assertEqual(decoded, server_public)
Esempio n. 38
0
 def test_server_public(self):
     server_public = \
         b"\x54\xFC\xBA\x24\xE9\x32\x49\x96" \
         b"\x93\x16\xFB\x61\x7C\x87\x2B\xB0" \
         b"\xC1\xD1\xFF\x14\x80\x04\x27\xC5" \
         b"\x94\xCB\xFA\xCF\x1B\xC2\xD6\x52"
     encoded = z85.encode(server_public)
     
     self.assertEqual(encoded, b"rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7")
     decoded = z85.decode(encoded)
     self.assertEqual(decoded, server_public)
Esempio n. 39
0
 def test_client_secret(self):
     client_secret = \
         b"\x7B\xB8\x64\xB4\x89\xAF\xA3\x67" \
         b"\x1F\xBE\x69\x10\x1F\x94\xB3\x89" \
         b"\x72\xF2\x48\x16\xDF\xB0\x1B\x51" \
         b"\x65\x6B\x3F\xEC\x8D\xFD\x08\x88"
     encoded = z85.encode(client_secret)
     
     self.assertEqual(encoded, b"D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs")
     decoded = z85.decode(encoded)
     self.assertEqual(decoded, client_secret)
Esempio n. 40
0
 def verify_peers(self):
     queried = 0
     nodes = self.engine.nodetree.get_all_nodes()
     random.shuffle(nodes)
     for x in nodes:
         if x.is_discovered():
             self.engine.txmap.create(Ping,
               [x.address, x.port, z85.encode(x.node_id)], self.engine)
             queried += 1
             if queried >= self.verify_limit:
                 break
Esempio n. 41
0
 def test_client_public(self):
     client_public = \
         b"\xBB\x88\x47\x1D\x65\xE2\x65\x9B" \
         b"\x30\xC5\x5A\x53\x21\xCE\xBB\x5A" \
         b"\xAB\x2B\x70\xA3\x98\x64\x5C\x26" \
         b"\xDC\xA2\xB2\xFC\xB4\x3F\xC5\x18"
     encoded = z85.encode(client_public)
     
     self.assertEqual(encoded, b"Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID")
     decoded = z85.decode(encoded)
     self.assertEqual(decoded, client_public)
Esempio n. 42
0
 def test_server_secret(self):
     server_secret = \
         b"\x8E\x0B\xDD\x69\x76\x28\xB9\x1D" \
         b"\x8F\x24\x55\x87\xEE\x95\xC5\xB0" \
         b"\x4D\x48\x96\x3F\x79\x25\x98\x77" \
         b"\xB4\x9C\xD9\x06\x3A\xEA\xD3\xB7"
     encoded = z85.encode(server_secret)
     
     self.assertEqual(encoded, b"JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6")
     decoded = z85.decode(encoded)
     self.assertEqual(decoded, server_secret)
Esempio n. 43
0
    def create_from_private_key(self, private_key):
        priv = PrivateKey(bytes.fromhex(private_key))
        publ = priv.public_key
        self.public_key = public_key = encode(publ._public_key)
        secret_key = encode(priv._private_key)

        base_filename = os.path.join(self.keys_dir, self.keyname)
        secret_key_file = "{0}.key_secret".format(base_filename)
        public_key_file = "{0}.key".format(base_filename)
        now = datetime.datetime.now()

        zmq.auth.certs._write_key_file(
            public_key_file, zmq.auth.certs._cert_public_banner.format(now),
            public_key)

        zmq.auth.certs._write_key_file(
            secret_key_file,
            zmq.auth.certs._cert_secret_banner.format(now),
            public_key,
            secret_key=secret_key)
Esempio n. 44
0
 def zap_loop(self, sender, **kwargs):
     self._zap_greenlet = gevent.getcurrent()
     sock = self.zap_socket
     time = gevent.core.time
     blocked = {}
     wait_list = []
     timeout = None
     while True:
         events = sock.poll(timeout)
         now = time()
         if events:
             zap = sock.recv_multipart()
             version = zap[2]
             if version != b'1.0':
                 continue
             domain, address, _, kind = zap[4:8]
             credentials = zap[8:]
             if kind == b'CURVE':
                 credentials[0] = z85.encode(credentials[0])
             elif kind not in [b'NULL', b'PLAIN']:
                 continue
             response = zap[:4]
             if self.authenticate(domain, address, kind, credentials):
                 user = dump_user(domain, address, kind, *credentials[:1])
                 response.extend([b'200', b'SUCCESS', user, b''])
                 sock.send_multipart(response)
             else:
                 try:
                     expire, delay = blocked[address]
                 except KeyError:
                     delay = random.random()
                 else:
                     if now >= expire:
                         delay = random.random()
                     else:
                         delay *= 2
                         if delay > 100:
                             delay = 100
                 expire = now + delay
                 bisect.bisect(wait_list, (expire, address, response))
                 blocked[address] = expire, delay
         while wait_list:
             expire, address, response = wait_list[0]
             if now < expire:
                 break
             wait_list.pop(0)
             response.extend([b'400', b'FAIL', b'', b''])
             sock.send_multipart(response)
             try:
                 if now >= blocked[address][0]:
                     blocked.pop(address)
             except KeyError:
                 pass
         timeout = (wait_list[0][0] - now) if wait_list else None
Esempio n. 45
0
 def zap_loop(self, sender, **kwargs):
     self._zap_greenlet = gevent.getcurrent()
     sock = self.zap_socket
     time = gevent.core.time
     blocked = {}
     wait_list = []
     timeout = None
     while True:
         events = sock.poll(timeout)
         now = time()
         if events:
             zap = sock.recv_multipart()
             version = zap[2]
             if version != b'1.0':
                 continue
             domain, address, _, kind = zap[4:8]
             credentials = zap[8:]
             if kind == b'CURVE':
                 credentials[0] = z85.encode(credentials[0])
             elif kind not in [b'NULL', b'PLAIN']:
                 continue
             response = zap[:4]
             if self.authenticate(domain, address, kind, credentials):
                 user = dump_user(domain, address, kind, *credentials[:1])
                 response.extend([b'200', b'SUCCESS', user, b''])
                 sock.send_multipart(response)
             else:
                 try:
                     expire, delay = blocked[address]
                 except KeyError:
                     delay = random.random()
                 else:
                     if now >= expire:
                         delay = random.random()
                     else:
                         delay *= 2
                         if delay > 100:
                             delay = 100
                 expire = now + delay
                 bisect.bisect(wait_list, (expire, address, response))
                 blocked[address] = expire, delay
         while wait_list:
             expire, address, response = wait_list[0]
             if now < expire:
                 break
             wait_list.pop(0)
             response.extend([b'400', b'FAIL', b'', b''])
             sock.send_multipart(response)
             try:
                 if now >= blocked[address][0]:
                     blocked.pop(address)
             except KeyError:
                 pass
         timeout = (wait_list[0][0] - now) if wait_list else None
Esempio n. 46
0
 def test_generate_from_public_key(self):
     self.ironhouse.daemon_context, self.ironhouse.daemon_auth = self.ironhouse.secure_context(
         async=True)
     self.ironhouse.add_public_key(encode(self.public_key.encode()))
     self.assertTrue(listdir(self.ironhouse.authorized_keys_dir),
                     'public keys dir not created')
     self.assertTrue(
         exists('{}/{}.key'.format(self.ironhouse.authorized_keys_dir,
                                   self.ironhouse.keyname)),
         'public key not generated')
     self.ironhouse.daemon_auth.stop()
Esempio n. 47
0
 def verify_peers(self):
     queried = 0
     nodes = self.engine.nodetree.get_all_nodes()
     random.shuffle(nodes)
     for x in nodes:
         if x.is_discovered():
             self.engine.txmap.create(
                 Ping, [x.address, x.port,
                        z85.encode(x.node_id)], self.engine)
             queried += 1
             if queried >= self.verify_limit:
                 break
Esempio n. 48
0
    def add_verifying_key(self, vk: str):
        # Convert to bytes if hex string
        bvk = bytes.fromhex(vk)

        try:
            pk = crypto_sign_ed25519_pk_to_curve25519(bvk)
        # Error is thrown if the VK is not within the possibility space of the ED25519 algorithm
        except RuntimeError:
            self.log.error('ED25519 Cryptographic error. The key provided is not within the cryptographic key space.')
            return

        zvk = z85.encode(pk).decode('utf-8')
        _write_key_file(self.cert_dir / f'{vk}.key', banner=_cert_public_banner, public_key=zvk)
Esempio n. 49
0
 def _zap_handler(self, message):
     """
     http://rfc.zeromq.org/spec:27
     """
     (zid, delimiter, version, sequence, domain, address, identity,
      mechanism, key) = message
     assert version == b'1.0'
     assert mechanism == b'CURVE'
     try:
         user_id = self.trusted_keys[key]
     except KeyError:
         user_id = z85.encode(key)
     reply = [zid, delimiter, version, sequence, b'200', b'OK',
              user_id, b'']
     self.zap_socket.send_multipart(reply)
Esempio n. 50
0
 def curve_user_id(self, client_public_key):
     """Return the User-Id corresponding to a CURVE client's public key
     
     Default implementation uses the z85-encoding of the public key.
     
     Override to define a custom mapping of public key : user-id
     
     This is only called on successful authentication.
     
     Parameters
     ----------
     client_public_key: bytes
         The client public key used for the given message
     
     Returns
     -------
     user_id: unicode
         The user ID as text
     """
     return z85.encode(client_public_key).decode('ascii')
Esempio n. 51
0
def test_find_nodes(root, closeme):
    # seed
    net = Network([], root)
    net.join()
    node = net.get_local()
    seeds = ["{0}:{1}:{2}".format(node['address'], node['port'], node['node_id'])]
    closeme.append(net)
    # can find self
    assert net.find_nodes(node['node_id']) != None

    # check for consistency across nodes
    net2 = Network(seeds, root)
    net2.join()
    closeme.append(net2)
    net3 = Network(seeds, root)
    net3.join()
    closeme.append(net3)

    # some more random nodes
    for _ in range(20):
        n = Network(seeds, root)
        n.join()
        closeme.append(n)

    # give them a bit of time to register with the seed
    time.sleep(2)

    # find a random id
    target = z85.encode(generate_random())
    
    # just pull out the id's for comparison
    nodes = [ x['node_id'] for x in net2.find_nodes(target, 5) ]
    # same response from other nodes
    assert nodes == [ x['node_id'] for x in net3.find_nodes(target, 5) ]
    
    # check that the routing agrees they're in distance order
    # need to transform back to raw bytes
    nodes = [ z85.decode(x) for x in nodes ]
    nodes2 = list(nodes)
    distance_sort(nodes2, z85.decode(target))
    assert nodes == nodes2
Esempio n. 52
0
    def test_trusted_curve_with_wrong_peer_public_key(self):
        from pseud import Client, Server
        from pseud.utils import register_rpc
        server_id = b'server'
        endpoint = 'inproc://{}'.format(__name__).encode()
        endpoint = b'tcp://127.0.0.1:8998'
        server_public, server_secret = zmq.curve_keypair()

        server = Server(server_id, security_plugin='trusted_curve',
                        public_key=server_public,
                        secret_key=server_secret,
                        io_loop=self.io_loop)
        server.bind(endpoint)

        alice_public, alice_secret = \
            server.auth_backend.known_identities[b'alice']
        client = Client(server_id,
                        user_id=b'alice',
                        security_plugin='trusted_curve',
                        public_key=alice_public,
                        secret_key=alice_secret,
                        peer_public_key=z85.encode(b'R' * 32),
                        timeout=.5,
                        io_loop=self.io_loop)
        client.connect(endpoint)
        assert server.socket.mechanism == zmq.CURVE
        assert client.socket.mechanism == zmq.CURVE

        yield server.start()
        yield client.start()

        register_rpc(name='string.lower')(str.lower)

        with pytest.raises(TimeoutError):
            yield client.string.lower('BAR')
        server.stop()
        client.stop()
Esempio n. 53
0
 def handle_authentication(self, sock):
     '''Restrict connections to approved clients.'''
     allow = False
     auth = sock.recv_multipart()
     version, sequence, domain, address, identity, mechanism = auth[:6]
     assert version == '1.0'
     if mechanism == 'CURVE':
         creds = z85.encode(auth[6])
         if domain == 'building.outgoing':
             allow = creds in self.allow_sub
         elif domain == 'building.incoming':
             allow = creds in self.allow_pub
     elif mechanism == 'NULL':
         allow, creds = True, ''
     else:
         creds = ''
     _log.info('{} {} at {} via {} {}'.format(
             'allow' if allow else 'deny', address, domain,
             mechanism, creds))
     if allow:
         reply = [version, sequence, "200", "OK", "", ""]
     else:
         reply = [version, sequence, "400", "Forbidden", "", ""]
     sock.send_multipart(reply)
Esempio n. 54
0
 def poll_random(self):
     # should really find a stale bucket not just random
     self.engine.txmap.create(FindNodes,
               [z85.encode(generate_random())], self.engine)
Esempio n. 55
0
 def _send_query(self):
     self.engine.txmap.create(FindNodes,
               [z85.encode(id_for_key(self.key))], self.engine, callback=self._closest)
Esempio n. 56
0
 def poll_neighbours(self):
     self.engine.txmap.create(FindNodes,
               [z85.encode(self.engine.node.node_id)], self.engine)