Beispiel #1
0
    def __init__(self, addr, port, node_id, listener, secret_key, secure=True):
        """
        Creates a new server (bound but not dispatching messages)
        @param addr: IP address of this node
        @param port: Port number to listen on
        @param node_id: Public key (z85 encoded) of this node
        @param listener: Callback object to receive handle_* function calls
        """
        self.ctx = zmq.Context()
        self.node = pack_node(addr, port, node_id)
        self.shutdown = False
        self.listener = listener

        self.sock = Socket(self.ctx, zmq.ROUTER)
        self.sock.identity = node_id
        # self.sock.router_handover = 1 # allow peer reconnections with same id
        # enable curve encryption/auth
        if secure:
            if not Server.auth:
                Server.auth = ThreadAuthenticator()
                Server.auth.start()
                Server.auth.configure_curve(domain='*',
                                            location=CURVE_ALLOW_ANY)
            self.sock.curve_server = True
            self.sock.curve_secretkey = z85.decode(secret_key)
            self.sock.curve_publickey = z85.decode(node_id)
        self.sock.bind("tcp://*:{0}".format(port))
        LOGGER.info("S listening.")
Beispiel #2
0
    def __init__(self, addr, port, node_id, listener, secret_key, secure=True):
        """
        Creates a new server (bound but not dispatching messages)
        @param addr: IP address of this node
        @param port: Port number to listen on
        @param node_id: Public key (z85 encoded) of this node
        @param listener: Callback object to receive handle_* function calls
        """
        self.ctx = zmq.Context()
        self.node = pack_node(addr, port, node_id)
        self.shutdown = False
        self.listener = listener

        self.sock = Socket(self.ctx, zmq.ROUTER)
        self.sock.identity = node_id
        # self.sock.router_handover = 1 # allow peer reconnections with same id
        # enable curve encryption/auth
        if secure:
            if not Server.auth:
                Server.auth = ThreadAuthenticator()
                Server.auth.start()
                Server.auth.configure_curve(domain='*',
                                            location=CURVE_ALLOW_ANY)
            self.sock.curve_server = True
            self.sock.curve_secretkey = z85.decode(secret_key)
            self.sock.curve_publickey = z85.decode(node_id)
        self.sock.bind("tcp://*:{0}".format(port))
        LOGGER.info("S listening.")
Beispiel #3
0
    def __init__(self, node, peer, ctx=None, secure=True):
        """
        Create a new connection to the specified peer.
        @param node: Node obj of this node
        @param peer: Peer (Node obj) to create connection to
        @param ctx: ZMQ context or autocreate if None
        """
        self.node = node
        self.peer = peer
        # abbreviated peer id for logging/debugging
        self.peer_label = peer.node_id[:6] + '..'
        self.node_header = pack_node(node.address, node.port, node.node_id)
        if not ctx:
            self.ctx = zmq.Context()
            self.ctx_managed = True
        else:
            self.ctx = ctx
            self.ctx_managed = False

        self.socket = Socket(self.ctx, zmq.DEALER)
        self.socket.identity = node.node_id
        if secure:
            self.socket.curve_publickey = z85.decode(node.node_id)
            self.socket.curve_secretkey = z85.decode(node.secret_key)
            self.socket.curve_serverkey = z85.decode(peer.node_id)
        self.socket.connect("tcp://{0}:{1}".format(peer.address, peer.port))
        LOGGER.info("C (%s) connected.", self.peer_label)
Beispiel #4
0
    def __init__(self, node, peer, ctx=None, secure=True):
        """
        Create a new connection to the specified peer.
        @param node: Node obj of this node
        @param peer: Peer (Node obj) to create connection to
        @param ctx: ZMQ context or autocreate if None
        """
        self.node = node
        self.peer = peer
        # abbreviated peer id for logging/debugging
        self.peer_label = peer.node_id[:6] + '..'
        self.node_header = pack_node(node.address, node.port, node.node_id)
        if not ctx:
            self.ctx = zmq.Context()
            self.ctx_managed = True
        else:
            self.ctx = ctx
            self.ctx_managed = False

        self.socket = Socket(self.ctx, zmq.DEALER)
        self.socket.identity = node.node_id
        if secure:
            self.socket.curve_publickey = z85.decode(node.node_id)
            self.socket.curve_secretkey = z85.decode(node.secret_key)
            self.socket.curve_serverkey = z85.decode(peer.node_id)
        self.socket.connect("tcp://{0}:{1}".format(peer.address, peer.port))
        LOGGER.info("C (%s) connected.", self.peer_label)
Beispiel #5
0
    def reset(self, public_key=None, secret_key=None):
        """
        Remove any existing state and reset as a new node.
        """
        if not public_key:
            public_key, secret_key = zmq.curve_keypair()
            public_key = z85.decode(public_key)
            secret_key = z85.decode(secret_key)
        else:
            secret_key = z85.decode(secret_key)
            public_key = z85.decode(public_key)
            if public_key and HAS_NACL:
                computed_key = str(PrivateKey(secret_key).public_key)
                assert (computed_key == public_key)

        self.node = Node(self.addr, self.port, public_key, secret_key)
        self.hashtabe = {}
        if HAS_NACL:
            self.secret_key = PrivateKey(self.node.secret_key)
        self.nodetree = RoutingZone(self.node.node_id)
        # ensure we exist in own tree
        self.nodetree.add(self.node)
        self.txmap = transaction.TxMap()
        self.defrag = transport.DefragMap()
        self._dump_state()
Beispiel #6
0
 def format_node(node):
     if self.node_id == node.node_id:
         return '{{** {0} **|{1}:{2}}}' \
             .format(binascii.hexlify(z85.decode(node.node_id)),
                     node.address, node.port)
     return '{{{0}|{1}:{2}}}' \
         .format(binascii.hexlify(z85.decode(node.node_id)),
                 node.address, node.port)
Beispiel #7
0
def distance(node_id1, node_id2):
    """
    The XOR distance betwen two keys/nodes.
    @param node_id1: Node id/key 1 as hex
    @param node_id2: Node id/key 2 as hex
    @return: The distance as long
    """
    return long(binascii.hexlify(z85.decode(node_id1)), 16) ^ \
        long(binascii.hexlify(z85.decode(node_id2)), 16)
Beispiel #8
0
 def test_generate_certificates(self):
     self.ironhouse.generate_certificates(self.sk, wipe_certs=True)
     self.assertTrue(listdir(self.ironhouse.authorized_keys_dir),
                     'public keys dir not created')
     self.assertEqual(self.private_key,
                      decode(self.ironhouse.secret).hex(),
                      'secret key generation is incorrect')
     self.assertEqual(self.public_key,
                      decode(self.ironhouse.public_key).hex(),
                      'public key generation is incorrect')
Beispiel #9
0
 def test_generate_from_private_key(self):
     makedirs(self.ironhouse.keys_dir, exist_ok=True)
     self.ironhouse.create_from_private_key(self.private_key)
     self.assertTrue(listdir(self.ironhouse.authorized_keys_dir),
                     'public keys dir not created')
     self.assertEqual(self.private_key,
                      decode(self.ironhouse.secret).hex(),
                      'secret key generation is incorrect')
     self.assertEqual(self.public_key,
                      decode(self.ironhouse.public_key).hex(),
                      'public key generation is incorrect')
Beispiel #10
0
 def parse_message(self, msg):
     self.target = z85.decode(msg.pop(0))
     # include peers that may be in bad states in case they have come good? will eventually be evicted
     self.closest = self.engine.nodetree.closest_to(self.target)
     self.unqueried = list(self.closest)  # shallow is fine
     self.queried = []
     self.outstanding = {}  # peer_id -> query time
Beispiel #11
0
 def test_generate_from_private_key(self):
     self.ironhouse.create_from_private_key(self.private_key)
     self.assertTrue(listdir(self.ironhouse.public_keys_dir),
                     'public keys dir not created')
     self.assertTrue(listdir(self.ironhouse.secret_keys_dir),
                     'secret keys dir not created')
     self.assertTrue(listdir(self.ironhouse.keys_dir),
                     'certificate keys dir not created')
     self.assertTrue(exists(self.ironhouse.secret_file),
                     'secret keys not created')
     self.assertEqual(self.private_key,
                      decode(self.ironhouse.secret).hex(),
                      'secret key generation is incorrect')
     self.assertEqual(self.public_key,
                      decode(self.ironhouse.public_key).hex(),
                      'public key generation is incorrect')
Beispiel #12
0
 def parse_message(self, msg):
     self.target = z85.decode(msg.pop(0))
     # include peers that may be in bad states in case they have come good? will eventually be evicted
     self.closest = self.engine.nodetree.closest_to(self.target)
     self.unqueried = list(self.closest)  # shallow is fine
     self.queried = []
     self.outstanding = {} # peer_id -> query time
Beispiel #13
0
 def setupSigning(self):
     # Setup its signer from the signing key stored at disk and for all
     # verification keys stored at disk, add Verifier
     _, sk = self.selfSigKeys
     self.signer = Signer(z85.decode(sk))
     for vk in self.getAllVerKeys():
         self.addVerifier(vk)
Beispiel #14
0
    async def authenticate(self, target_public_key, ip, port=None):
        if target_public_key == self.public_key: return True
        try:
            PublicKey(decode(target_public_key))
        except Exception as e:
            log.debug('Invalid public key')
            return False
        server_url = 'tcp://{}:{}'.format(ip, port or self.auth_port)
        log.debug('authenticating {}...'.format(server_url))
        client = self.ctx.socket(zmq.REQ)
        client.setsockopt(zmq.LINGER, 0)
        client = self.secure_socket(client, target_public_key)
        client.connect(server_url)
        client.send(self.vk.encode())
        authorized = False

        try:
            msg = await asyncio.wait_for(client.recv(), 0.5)
            msg = msg.decode()
            log.debug('got secure reply {}, {}'.format(msg, target_public_key))
            received_public_key = self.vk2pk(msg)
            if self.auth_validate(
                    msg) == True and target_public_key == received_public_key:
                self.create_from_public_key(received_public_key)
                authorized = True
        except Exception as e:
            log.debug('no reply from {} after waiting...'.format(server_url))
            authorized = None

        client.disconnect(server_url)
        client.close()
        self.auth.stop()

        return authorized
Beispiel #15
0
 def start(self, node_id, secret_key=None):
     if node_id:
         self.reset(node_id, secret_key)
     self.poller.register(self.udpserver.fileno(), zmq.POLLIN)
     for endpoint in self.seeds:
         addr, port, id = endpoint.split(':', 2)
         self.nodetree.add(Node(addr, int(port), z85.decode(id)))
Beispiel #16
0
 def setupSigning(self):
     # Setup its signer from the signing key stored at disk and for all
     # verification keys stored at disk, add Verifier
     _, sk = self.selfSigKeys
     self.signer = Signer(z85.decode(sk))
     for vk in self.getAllVerKeys():
         self.addVerifier(vk)
Beispiel #17
0
 def configure_curve(self, domain="*", location=None):
     self.clients = {}
     for filename in os.listdir(location):
         if filename.endswith('.key'):
             path = os.path.join(location, filename)
             public, _, user_id = load_certificate(path)
             log.debug("Allow connections from %s", user_id)
             self.clients[z85.decode(public)] = user_id
Beispiel #18
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)
Beispiel #19
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)
Beispiel #20
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)
Beispiel #21
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)
Beispiel #22
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
Beispiel #23
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)
Beispiel #24
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)
Beispiel #25
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)
Beispiel #26
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)
Beispiel #27
0
 def __init__(
     self,
     socket: zmq.Socket,
     endpoint: str,
     *,
     curve_keys: typing.Optional[CurveKeys] = None,
 ):
     """
     Parameters:
         ctx: The ZeroMQ context
         endpoint: The server endpoint
         curvekeys: If given, the CURVE keys that will be used to establish
                    the connection to the backend
     """
     self._socket = socket
     if curve_keys:
         self._socket.curve_serverkey = z85.decode(curve_keys.serverkey)
         self._socket.curve_publickey = z85.decode(curve_keys.publickey)
         self._socket.curve_secretkey = z85.decode(curve_keys.secretkey)
     self._socket.connect(endpoint)
Beispiel #28
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
Beispiel #29
0
 def is_authenticated(self, user_id):
     result = False
     if user_id in self.trusted_keys:
         result = True
     try:
         if z85.decode(user_id) in self.trusted_keys:
             result = True
     except ValueError:
         pass
     if user_id in self.trusted_keys.values():
         result = True
     return result
Beispiel #30
0
    def remove_public_key(self, public_key):
        if self.public_key == public_key: return
        keyname = decode(public_key).hex()
        base_filename = join(self.authorized_keys_dir, keyname)
        public_key_file = "{0}.key".format(base_filename)
        if exists(public_key_file):
            os.remove(public_key_file)

        log.debug('{} has remove {} from its authorized list'.format(
            os.getenv('HOST_IP', '127.0.0.1'), public_key))
        self.reconfigure_curve()
        self.authorized_keys[public_key] = False
Beispiel #31
0
 def is_authenticated(self, user_id):
     result = False
     if user_id in self.trusted_keys:
         result = True
     try:
         if z85.decode(user_id) in self.trusted_keys:
             result = True
     except ValueError:
         pass
     if user_id in self.trusted_keys.values():
         result = True
     return result
Beispiel #32
0
def bit_number(node_id, bit):
    """
    Returns value of the specified bit, counting from
    MSB = 0, for the specified node_id/key.
    The node_id is treated as a key of KEY_BITS length
    regardless of current size.
    @param node_id: Node id/key as hex
    @param bit: Bit position to return
    @return: Value at bit position 'bit' or 0 if > KEY_BITS
    """
    if bit >= KEY_BITS:
        return 0
    return (long(binascii.hexlify(z85.decode(node_id)), 16) \
        >> (KEY_BITS - 1 - bit)) & 1
Beispiel #33
0
 def __init__(self,
              ctx: zmq.asyncio.Context,
              tmpdir,
              secretkey: typing.Optional[bytes] = None):
     """
     Parameters:
         ctx: The ZeroMQ context
         tmpdir: Temporary directory where the sockets are created
         secretkey: CURVE secret key
     """
     self._mock_server_endpoint = f"ipc://{tmpdir.join('server.endpoint')}"
     self._socket = ctx.socket(zmq.ROUTER)
     if secretkey:
         self._socket.curve_server = 1
         self._socket.curve_secretkey = z85.decode(secretkey)
     self._socket.bind(self._mock_server_endpoint)
     self._router_id = None
     self._mock_event_endpoint = f"ipc://{tmpdir.join('event.endpoint')}"
     self._event_socket = ctx.socket(zmq.PUB)
     if secretkey:
         self._event_socket.curve_server = 1
         self._event_socket.curve_secretkey = z85.decode(secretkey)
     self._event_socket.bind(self._mock_event_endpoint)
Beispiel #34
0
 def decode(self, ctext: T) -> Optional[U]:
     """
     Performs Z85 decoding
     """
     ctext_len = len(ctext)
     if ctext_len % 5:
         logger.trace(
             f"Failed to decode Z85 because length must be a multiple of 5, not '{ctext_len}'"
         )
         return None
     try:
         return z85.decode(ctext).decode("utf-8")
     except Exception:
         return None
Beispiel #35
0
def encode_key(key):
    '''Base64-encode and return a key in a URL-safe manner.'''
    # There is no easy way to test if key is already base64 encoded and ASCII decoded. This seems the best way.
    if len(key) % 4 != 0:
        return key
    key = key if isinstance(key, bytes) else key.encode("utf-8")
    try:
        assert len(key) in (32, 40)
    except AssertionError:
        raise AssertionError(
            "Assertion error while encoding key:{}, len:{}".format(
                key, len(key)))
    if len(key) == 40:
        key = z85.decode(key)
    return base64.urlsafe_b64encode(key)[:-1].decode("ASCII")
Beispiel #36
0
    def test_keypair(self):
        """test curve_keypair"""
        try:
            public, secret = zmq.curve_keypair()
        except zmq.ZMQError:
            raise SkipTest("CURVE unsupported")

        self.assertEqual(type(secret), bytes)
        self.assertEqual(type(public), bytes)
        self.assertEqual(len(secret), 40)
        self.assertEqual(len(public), 40)

        # verify that it is indeed Z85
        bsecret, bpublic = [z85.decode(key) for key in (public, secret)]
        self.assertEqual(type(bsecret), bytes)
        self.assertEqual(type(bpublic), bytes)
        self.assertEqual(len(bsecret), 32)
        self.assertEqual(len(bpublic), 32)
    def test_keypair(self):
        """test curve_keypair"""
        try:
            public, secret = zmq.curve_keypair()
        except zmq.ZMQError:
            raise SkipTest("CURVE unsupported")

        self.assertEqual(type(secret), bytes)
        self.assertEqual(type(public), bytes)
        self.assertEqual(len(secret), 40)
        self.assertEqual(len(public), 40)

        # verify that it is indeed Z85
        bsecret, bpublic = [z85.decode(key) for key in (public, secret)]
        self.assertEqual(type(bsecret), bytes)
        self.assertEqual(type(bpublic), bytes)
        self.assertEqual(len(bsecret), 32)
        self.assertEqual(len(bpublic), 32)
Beispiel #38
0
 def handle_hello(self, user_id, routing_id, message_uuid, message):
     login, password = msgpack_unpackb(message)
     if login in self.user_map and self.user_map[login] == password:
         key = z85.decode(self.pending_keys[routing_id])
         self.trusted_keys[key] = login
         self.login2peer_id_mapping[login] = routing_id
         try:
             del self.login2peer_id_mapping[self.pending_keys[routing_id]]
         except KeyError:
             pass
         reply = 'Welcome {!r}'.format(login).encode()
         status = AUTHENTICATED
     else:
         reply = b'Authentication Error'
         status = UNAUTHORIZED
     logger.debug('Sending Hello reply: {!r}'.format(reply))
     self.rpc.send_message([routing_id, EMPTY_DELIMITER, VERSION,
                            message_uuid, status, reply])
Beispiel #39
0
 def handle_hello(self, user_id, routing_id, message_uuid, message):
     login, password = self.packer.unpackb(message)
     if login in self.user_map and self.user_map[login] == password:
         key = z85.decode(self.pending_keys[routing_id])
         self.trusted_keys[key] = login
         self.login2peer_id_mapping[login] = routing_id
         try:
             del self.login2peer_id_mapping[self.pending_keys[routing_id]]
         except KeyError:
             pass
         reply = 'Welcome {!r}'.format(login).encode()
         status = AUTHENTICATED
     else:
         reply = b'Authentication Error'
         status = UNAUTHORIZED
     logger.debug('Sending Hello reply: {!r}'.format(reply))
     self.rpc.send_message([
         routing_id, EMPTY_DELIMITER, VERSION, message_uuid, status, reply
     ])
Beispiel #40
0
    def create_from_public_key(self, public_key):
        if self.public_key == public_key:
            return
        keyname = decode(public_key).hex()
        base_filename = os.path.join(self.public_keys_dir, keyname)
        public_key_file = "{0}.key".format(base_filename)
        now = datetime.datetime.now()

        if os.path.exists(public_key_file):
            log.debug('Public cert for {} has already been created.'.format(
                public_key))
            return

        os.makedirs(self.public_keys_dir, exist_ok=True)
        log.info(
            'Adding new public key cert {} to the system.'.format(public_key))

        zmq.auth.certs._write_key_file(
            public_key_file, zmq.auth.certs._cert_public_banner.format(now),
            public_key)
Beispiel #41
0
    def _zap_handler(self, message):
        """
        `ZAP <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'
        for known_identity, pair in self.known_identities.items():
            if key == z85.decode(pair[0]):
                response_code = b'200'
                response_msg = b'OK'
                break
        else:
            known_identity = b''
            response_code = b'400'
            response_msg = b'Unauthorized'

        reply = [zid, delimiter, version, sequence, response_code,
                 response_msg, known_identity, b'']
        self.zap_socket.send_multipart(reply)
    def test_curve_public(self):
        """test curve_public"""
        try:
            public, secret = zmq.curve_keypair()
        except zmq.ZMQError:
            raise SkipTest("CURVE unsupported")
        if zmq.zmq_version_info() < (4, 2):
            raise SkipTest("curve_public is new in libzmq 4.2")

        derived_public = zmq.curve_public(secret)

        self.assertEqual(type(derived_public), bytes)
        self.assertEqual(len(derived_public), 40)

        # verify that it is indeed Z85
        bpublic = z85.decode(derived_public)
        self.assertEqual(type(bpublic), bytes)
        self.assertEqual(len(bpublic), 32)

        # verify that it is equal to the known public key
        self.assertEqual(derived_public, public)
Beispiel #43
0
    def test_curve_public(self):
        """test curve_public"""
        try:
            public, secret = zmq.curve_keypair()
        except zmq.ZMQError:
            raise SkipTest("CURVE unsupported")
        if zmq.zmq_version_info() < (4,2):
            raise SkipTest("curve_public is new in libzmq 4.2")

        derived_public = zmq.curve_public(secret)

        self.assertEqual(type(derived_public), bytes)
        self.assertEqual(len(derived_public), 40)

        # verify that it is indeed Z85
        bpublic = z85.decode(derived_public)
        self.assertEqual(type(bpublic), bytes)
        self.assertEqual(len(bpublic), 32)

        # verify that it is equal to the known public key
        self.assertEqual(derived_public, public)
Beispiel #44
0
    async def authenticate(self, target_public_key, ip, port=None):
        if target_public_key == self.public_key: return 'authorized'
        try:
            PublicKey(decode(target_public_key))
        except Exception as e:
            log.debug('Invalid public key')
            return 'invalid'
        server_url = 'tcp://{}:{}'.format(ip, port or self.auth_port)
        log.debug('{} sending handshake to {}...'.format(
            os.getenv('HOST_IP', '127.0.0.1'), server_url))
        client = self.ctx.socket(zmq.REQ)
        client.setsockopt(zmq.LINGER, 0)
        client = self.secure_socket(client, self.secret, self.public_key,
                                    target_public_key)
        client.connect(server_url)
        client.send_multipart(
            [self.vk.encode(),
             os.getenv('HOST_IP', '127.0.0.1').encode()])
        authorized = 'unauthorized'

        try:
            msg = await asyncio.wait_for(client.recv(), AUTH_TIMEOUT)
            msg = msg.decode()
            log.debug('{} got secure reply {}, {}'.format(
                os.getenv('HOST_IP', '127.0.0.1'), msg, target_public_key))
            received_public_key = self.vk2pk(msg)
            if self.auth_validate(
                    msg) == True and target_public_key == received_public_key:
                self.add_public_key(received_public_key)
                self.pk2vk[received_public_key] = msg
                authorized = 'authorized'
        except Exception as e:
            log.debug('{} got no reply from {} after waiting...'.format(
                os.getenv('HOST_IP', '127.0.0.1'), server_url))
            authorized = 'no_reply'

        client.disconnect(server_url)
        client.close()

        return authorized
Beispiel #45
0
    def _zap_handler(self, message):
        """
        `ZAP <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'
        for known_identity, pair in self.known_identities.items():
            if key == z85.decode(pair[0]):
                response_code = b'200'
                response_msg = b'OK'
                break
        else:
            known_identity = b''
            response_code = b'400'
            response_msg = b'Unauthorized'

        reply = [
            zid, delimiter, version, sequence, response_code, response_msg,
            known_identity, b''
        ]
        self.zap_socket.send_multipart(reply)
Beispiel #46
0
    def add_public_key(self, public_key):
        if self.public_key == public_key: return
        keyname = decode(public_key).hex()
        base_filename = join(self.authorized_keys_dir, keyname)
        public_key_file = "{0}.key".format(base_filename)
        now = datetime.datetime.now()

        if exists(public_key_file):
            log.debug('Public cert for {} has already been created.'.format(
                public_key))
            return

        os.makedirs(self.authorized_keys_dir, exist_ok=True)
        log.info(
            'Adding new public key cert {} to the system.'.format(public_key))

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

        log.debug('{} has added {} to its authorized list'.format(
            os.getenv('HOST_IP', '127.0.0.1'), public_key))
        self.reconfigure_curve()
        self.authorized_keys[public_key] = True
Beispiel #47
0
def decode(data):
    if verbose:
        print "Decoding {" + data + "} (total " + str(len(data)) + " bytes)"
        print z85.decode(data)
    else:
        sys.stdout.write(z85.decode(data))
Beispiel #48
0
def encode_key(key):
    '''Base64-encode and return a key in a URL-safe manner.'''
    assert len(key) in (32, 40)
    if len(key) == 40:
        key = z85.decode(key)
    return base64.urlsafe_b64encode(key)[:-1]
Beispiel #49
0
 def unpack_request(self, msg):
     peer_addr = msg.pop(0)
     peer_port = int(msg.pop(0))
     peer_id = z85.decode(msg.pop(0))
     self.peer = self.engine.verify_peer(peer_addr, peer_port, peer_id)
Beispiel #50
0
def z85_to_friendly(z):
    try:
        return z if isinstance(z, str) else hexToFriendly(hexlify(z85.decode(z)))
    except ValueError:
        return z
Beispiel #51
0
 def test_vk2pk(self):
     self.assertEqual(
         decode(self.ironhouse.vk2pk(self.vk)).hex(), self.public_key,
         'conversion of vk to pk failed')
Beispiel #52
0
 def verhex(self):
     if self.verKey:
         return hexlify(z85.decode(self.verKey))
     return None
Beispiel #53
0
def encode_key(key):
    '''Base64-encode and return a key in a URL-safe manner.'''
    assert len(key) in (32, 40)
    if len(key) == 40:
        key = z85.decode(key)
    return base64.urlsafe_b64encode(key)[:-1]
Beispiel #54
0
 def addVerifier(self, verkey):
     self.verifiers[verkey] = Verifier(z85.decode(verkey))
Beispiel #55
0
 def publicKeyRaw(self):
     return z85.decode(self.publicKey)
Beispiel #56
0
 def pubhex(self):
     return hexlify(z85.decode(self.publicKey))
Beispiel #57
0
 def prihex(self):
     return hexlify(z85.decode(self.priKey))
Beispiel #58
0
 def verKeyRaw(self):
     if self.verKey:
         return z85.decode(self.verKey)
     return None
Beispiel #59
0
 def keyhex(self):
     return hexlify(z85.decode(self.sigKey))