示例#1
0
def handshake_initiate(private_key, redis_client):
    try:
        request = expect_json_request(bottle.request, INITIATE_SCHEMA)

        symmetric_key = redis_get_cookie(
            redis_client, request[INITIATE_COOKIE_FIELD])
        cookie_sbox = SecretBox(symmetric_key)
        cookie = cookie_sbox.decrypt(
            str(request[INITIATE_COOKIE_FIELD]), encoder=Base64Encoder)

        if len(cookie) != 2 * CURVE25519_KEY_BYTES:
            bottle.response.status = HTTP_INTERNAL_SERVER_ERROR
            return {'error': 'An invalid cookie was sent to the client.'}
        client_transient_pkey = PublicKey(cookie[0:CURVE25519_KEY_BYTES])
        transient_skey = PrivateKey(cookie[CURVE25519_KEY_BYTES:])

        if request[INITIATE_CLIENT_TRANSIENT_PKEY_FIELD] != \
           client_transient_pkey.encode(Base64Encoder):
            raise InvalidClientRequest(
                'Initiate: non matching transient public keys.')

        vouch_json = open_box(request[INITIATE_VOUCH_FIELD],
                              transient_skey, client_transient_pkey)
        vouch = parse_and_verify_json(vouch_json, VOUCH_SCHEMA)

        client_pkey = PublicKey(
            str(vouch[VOUCH_CLIENT_PKEY_FIELD]), encoder=Base64Encoder)
        vouch_for_transient_pkey = open_box(
            vouch[VOUCH_TRANSIENT_KEY_BOX_FIELD], private_key, client_pkey)
        if vouch_for_transient_pkey != client_transient_pkey.encode():
            raise InvalidClientRequest(
                'Initiate: non matching transient public keys.')

        resp = 'I believe you are {} and you want {}'.format(
            client_pkey.encode(Base64Encoder), vouch[VOUCH_MESSAGE_FIELD])
        print(resp)
        response_nonce = nacl.utils.random(Box.NONCE_SIZE)
        response_box = Box(transient_skey, client_transient_pkey)
        response_box_cipher = response_box.encrypt(
            resp, response_nonce, encoder=Base64Encoder)
        return {'response': response_box_cipher}
    except jsonschema.ValidationError as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': str(e)}
    except InvalidClientRequest as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': str(e)}
    except MissingCookie as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': str(e)}
    except CryptoError as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': 'Bad encryption in handshake.'}
    return {'error': ''}
示例#2
0
def test_box_seal(
        privalice, pubalice, privbob, pubbob, nonce, plaintext, ciphertext):
    pubalice = PublicKey(pubalice, encoder=HexEncoder)
    privalice = PrivateKey(privalice, encoder=HexEncoder)
    plaintext = binascii.unhexlify(plaintext)

    sealed = pubalice.seal(plaintext)
    unsealed = privalice.seal_open(sealed)
    assert plaintext == unsealed

    sealed2 = privalice.seal(plaintext)
    unsealed2 = privalice.seal_open(sealed2)
    assert plaintext == unsealed2
示例#3
0
    def processM1(self, msg):
        #print "processM1", self.petname
        self.theirTempPubkey = PublicKey(msg)
        self.db.update("UPDATE invitations SET theirTempPubkey=?"
                       " WHERE id=?",
                       (self.theirTempPubkey.encode(Hex), self.iid),
                       "invitations", self.iid)
        # theirTempPubkey will committed by our caller, in the same txn as
        # the message send

        my_privkey = self.getMyTempPrivkey()
        my_channel_record = self.getMyPublicChannelRecord()
        b = Box(my_privkey, self.theirTempPubkey)
        signedBody = b"".join([self.theirTempPubkey.encode(),
                               my_privkey.public_key.encode(),
                               my_channel_record.encode("utf-8")])
        my_sign = self.getMySigningKey()
        body = b"".join([b"i0:m2a:",
                         my_sign.verify_key.encode(),
                         my_sign.sign(signedBody)
                         ])
        nonce = os.urandom(Box.NONCE_SIZE)
        nonce_and_ciphertext = b.encrypt(body, nonce)
        #print "ENCRYPTED n+c", len(nonce_and_ciphertext), nonce_and_ciphertext.encode("hex")
        #print " nonce", nonce.encode("hex")
        msg2 = "i0:m2:"+nonce_and_ciphertext
        self.send(msg2)
        self.nextExpectedMessage = 2
示例#4
0
def handshake_hello(private_key, redis_client):
    try:
        request = expect_json_request(bottle.request, HELLO_SCHEMA)
        client_transient_pkey = PublicKey(
            str(request[HELLO_CLIENT_TRANSIENT_PKEY_FIELD]), Base64Encoder)

        zeros = open_box(request[HELLO_ZEROS_BOX_FIELD],
                         private_key, client_transient_pkey)
        if len(zeros) != HELLO_PADDING_BYTES:
            raise InvalidClientRequest(
                'zeros_box should contain exactly %d bytes of padding' %
                HELLO_PADDING_BYTES)

        transient_skey = PrivateKey.generate()
        cookie_plain = client_transient_pkey.encode() + \
                       transient_skey.encode()
        cookie_nonce = nacl.utils.random(SecretBox.NONCE_SIZE)
        symmetric_key = nacl.utils.random(SecretBox.KEY_SIZE)
        cookie_sbox = SecretBox(symmetric_key)
        cookie = cookie_sbox.encrypt(
            cookie_plain, cookie_nonce, encoder=Base64Encoder)
        redis_set_cookie(redis_client, cookie, symmetric_key)

        cookie_box = Box(private_key, client_transient_pkey)
        cookie_box_nonce = nacl.utils.random(Box.NONCE_SIZE)
        server_tpkey = transient_skey.public_key.encode(Base64Encoder)
        cookie_box_cipher = cookie_box.encrypt(json.dumps({
            COOKIE_SERVER_TRANSIENT_PKEY_FIELD: server_tpkey,
            COOKIE_COOKIE_FIELD: cookie
        }), cookie_box_nonce, encoder=Base64Encoder)

        response = {COOKIE_COOKIE_BOX_FIELD: cookie_box_cipher}
        jsonschema.validate(response, COOKIE_SCHEMA)
        return response
    except jsonschema.ValidationError:
        log.exception(e)
        bottle.response.status = HTTP_INTERNAL_SERVER_ERROR
        return {'error': 'A packet with an invalid JSON schema was generated.'}
    except InvalidClientRequest as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': str(e)}
    except CryptoError as e:
        log.exception(e)
        bottle.response.status = HTTP_BAD_REQUEST
        return {'error': 'bad encryption'}
    return {'error': ''}
示例#5
0
    def on_post(self, req, resp):
        configuration = req.context['configuration']

        if req.content_length:
            data = json.load(req.bounded_stream)
        else:
            raise Exception("No data.")

        if 'public_key' not in data:
            raise Exception("No public key.")

        db_session = req.context['db_session']

        user_public_key = PublicKey(data['public_key'].encode('utf-8'), encoder = nacl.encoding.Base64Encoder)

        user = db_session.query(db.User).filter(db.User.public_key == user_public_key.encode(nacl.encoding.RawEncoder)).first()

        if user is None:
            raise Exception("Public key unknown.")

        challenge_answer = nacl.utils.random(Box.NONCE_SIZE)
        challenge_uuid = str(uuid.uuid4())

        box = Box(configuration['server_key_pair'], user_public_key)

        challenge_box = box.encrypt(plaintext = challenge_answer, encoder = nacl.encoding.Base64Encoder)

        challenge = db.Challenge(
            uuid = challenge_uuid,
            user = user,
            answer_hash = nacl.hash.sha256(challenge_answer, encoder = nacl.encoding.RawEncoder)
        )

        db_session.add(challenge)
        db_session.commit()

        resp.status = falcon.HTTP_200
        resp.body = json.dumps({
            'uuid': challenge_uuid,
            'nonce': str(challenge_box.nonce.decode('utf-8')),
            'challenge': str(challenge_box.ciphertext.decode('utf-8'))
        })
示例#6
0
def encrypt(msg, private_key, public_key):
    """
    Encrypt message.

    :param bytes msg: message to be encrypted.
    :param bytes private_key: Private Key of encrypter.
    :param bytes public_key: Public Key of decrypter.
    :returns: The encrypted message.
    :rtype: nacl.utils.EncryptedMessage
    """
    return Box(PrivateKey(private_key),
               PublicKey(public_key)).encrypt(msg, random(Box.NONCE_SIZE))
示例#7
0
 def vouch(self, public_key):
     """
     given the public key of another user, asymmetrically encrypt the
     master key. this encryption inherently includes authentication so
     we don't need to also sign this block.
     """
     assert self._master_key is not None
     pkey = PublicKey(public_key, encoder=nacl.encoding.HexEncoder)
     box = Box(self.enc_key, pkey)
     encrypted = box.encrypt(self._master_key)
     data = {'version': VERSION, 'key': encrypted.hex()}
     return json.dumps(data).encode('ascii')
示例#8
0
    def encrypt(self, message, reciever_public_key):
        """Encrypt the message to send to a receiver. (public key encryption)

        Args:
            message (bytes): The message to be encrypted.
            reciever_public_key (bytes): The receiver's public key.

        Returns:
            bytes: The encrypted message
        """
        return Box(self.private_key,
                   PublicKey(reciever_public_key)).encrypt(message)
示例#9
0
def test_box_decode():
    pub = PublicKey(
        b"ec2bee2d5be613ca82e377c96a0bf2220d823ce980cdff6279473edc52862798",
        encoder=HexEncoder,
    )
    priv = PrivateKey(
        b"5c2bee2d5be613ca82e377c96a0bf2220d823ce980cdff6279473edc52862798",
        encoder=HexEncoder,
    )
    b1 = Box(priv, pub)
    b2 = Box.decode(b1._shared_key)
    assert b1._shared_key == b2._shared_key
示例#10
0
def test_box_optional_nonce(privalice, pubalice, privbob, pubbob, nonce,
                            plaintext, ciphertext):
    pubbob = PublicKey(pubbob, encoder=HexEncoder)
    privalice = PrivateKey(privalice, encoder=HexEncoder)

    box = Box(privalice, pubbob)

    encrypted = box.encrypt(binascii.unhexlify(plaintext), encoder=HexEncoder)

    decrypted = binascii.hexlify(box.decrypt(encrypted, encoder=HexEncoder))

    assert decrypted == plaintext
示例#11
0
    def from_chain(cls, chain, difficulty=1, difficulty_mode=0):
        blockchain = cls()
        blockchain.difficulty = difficulty
        blockchain.difficulty_mode = difficulty_mode
        for i in range(0, len(chain)):
            blockchain.append(chain[i])

        blockchain.sort()
        blockchain.address = blockchain[0]['node_address']
        blockchain.public_key = PublicKey(blockchain[0]['public_key'])

        return blockchain
示例#12
0
    def decrypt(self, message, sender_public_key):
        """Decrypt a received message. (public key encryption)

        Args:
            message (bytes): The encrypted message.
            sender_public_key (bytes): The public key of the sender.

        Returns:
            bytes: The decrypted message
        """
        return Box(self.private_key,
                   PublicKey(sender_public_key)).decrypt(message)
示例#13
0
def test_box_decryption(skalice, pkalice, skbob, pkbob, nonce, plaintext,
                        ciphertext):
    pkbob = PublicKey(pkbob, encoder=HexEncoder)
    skalice = PrivateKey(skalice, encoder=HexEncoder)

    box = Box(skalice, pkbob)

    nonce = binascii.unhexlify(nonce)
    decrypted = binascii.hexlify(
        box.decrypt(ciphertext, nonce, encoder=HexEncoder), )

    assert decrypted == plaintext
示例#14
0
def test_box_decryption_combined(privalice, pubalice, privbob, pubbob, nonce,
                                 plaintext, ciphertext):
    pubbob = PublicKey(pubbob, encoder=HexEncoder)
    privalice = PrivateKey(privalice, encoder=HexEncoder)

    box = Box(privalice, pubbob)

    combined = binascii.hexlify(
        binascii.unhexlify(nonce) + binascii.unhexlify(ciphertext), )
    decrypted = binascii.hexlify(box.decrypt(combined, encoder=HexEncoder))

    assert decrypted == plaintext
示例#15
0
    def crea_sesion_a(self, nombre):
        """
        Se escribe el archivo como nombreA_nombreB_values
        :param nombre: Usuario con quien se desea establecer la comunicación
        :return: devuelve el secreto calculado a partir de las llaves del usuario con el nombre
        especificado
        """
        dicti = self.solicita_llaves(nombre)
        if not dicti["ok"]:
            return "Error:\n" + dicti["detalles"]

        ikb = PublicKey(base64.b64decode(dicti["llave_identidad"]))
        mkb = PublicKey(base64.b64decode(dicti["pre_llave"]))
        # genera la llave efimera
        efk_priv = PrivateKey.generate()
        # calcula el secreto como: DH(IKA,MKB) || DH(EKA, IKB) || DH(EKA,MKB)
        b1 = Box(self.sk, mkb).shared_key()
        b2 = Box(efk_priv, ikb).shared_key()
        b3 = Box(efk_priv, mkb).shared_key()
        secreto = b1 + b2 + b3
        # Genera un diccionario para escribir en un archivo las llaves de Bob
        dicc = {
            'ikb': base64.b64encode(ikb.__bytes__()),
            'mkb': base64.b64encode(mkb.__bytes__()),
            'efk_pub': base64.b64encode(efk_priv.public_key.__bytes__()),
            'secreto': base64.b64encode(secreto),
            'kenv': "",
            'krecib': "",
            "establecida": False,
            "tipo": "A"
        }
        # escribe el archivo
        json.dump(dicc, open(self.nombre + "_" + nombre + "_values", "w"))
        self.secreto = secreto
        return secreto
    def _serialize_sign_encrypt(self,
                                data,
                                serialization_format="json",
                                pubkey_hex=None,
                                nacl=None,
                                threebot=None):
        """
        will sign any data with private key of our local 3bot private key
        if public_encryption_key given will then encrypt using the pub key given (as binary hex encoded key)

        :param data: can be a binary blob or a list of items, which will be converted to binary counterpart
        :param serialization_format: json or msgpack

        a list of following items

            int,float,str,binary,list and dict  -> stay in native format
            jsxobject -> jsxobject.json
            jsxdict -> jsxdict._data which is the source dict format of our jumpscale dict representation


        this gets serialized using the chosen format

        result is [3botid,serializeddata,signature]

        this then gets signed with private key of this threebot

        the serializeddata optionally gets encrypted with pubkey_hex (the person who asked for the info)

        :return: [3botid,serializeddata,signature]
        """
        if not nacl:
            nacl = self._nacl
        data2 = self._serialize(data,
                                serialization_format=serialization_format)

        if isinstance(data2, str):
            data2 = data2.encode()
        signature = nacl.sign(data2)

        if threebot:
            threebot_client = j.clients.threebot.client_get(threebot)
            data3 = threebot_client.encrypt_for_threebot(data2)
            tid = threebot_client.tid
        else:
            tid = j.tools.threebot.me.default.tid
            if pubkey_hex:
                assert len(pubkey_hex) == 64
                pubkey = PublicKey(binascii.unhexlify(pubkey_hex))
                data3 = nacl.encrypt(data2, public_key=pubkey)
            else:
                data3 = data2
        return [tid, data3, signature]
示例#17
0
文件: utils.py 项目: yingziwu/perma
def decrypt_from_perma_payments(ciphertext, encoder=encoding.Base64Encoder):
    """
    Decrypt bytes encrypted by perma-payments.
    """
    box = Box(
        PrivateKey(
            settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_secret_key'], encoder=encoder
        ),
        PublicKey(
            settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_payments_public_key'], encoder=encoder
        )
    )
    return box.decrypt(ciphertext, encoder=encoder)
示例#18
0
 def handle_N(self, message):
     """
     encryption key negotiation
     """
     pub_key = PublicKey(message[:32])
     auth = message[32:64]
     if blake2b(bytes(pub_key) + get_cas_secret(), encoder=RawEncoder) != auth:
         raise RuntimeError('Bad Client Auth! %s' % auth)
     self.client_box = Box(self.private_key, pub_key)
     if self.debug:
         print('server public_key: %s' % self.public_key.hex())
         print('client public_key: %s' % bytes(pub_key).hex())
     return [b'OK']
示例#19
0
 def rpc_dispute_close(self, sender, pubkey, encrypted):
     try:
         box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey))
         res = box.decrypt(encrypted)
         resolution_json = json.loads(res, object_pairs_hook=OrderedDict)
         close_dispute(resolution_json, self.db, self.get_message_listener(),
                       self.get_notification_listener(), self.multiplexer.testnet)
         self.router.addContact(sender)
         self.log.info("Contract dispute closed by %s" % sender)
         return ["True"]
     except Exception:
         self.log.error("unable to parse disputed close message from %s" % sender)
         return ["False"]
示例#20
0
文件: utils.py 项目: yingziwu/perma
def encrypt_for_perma_payments(message, encoder=encoding.Base64Encoder):
    """
    Basic public key encryption ala pynacl.
    """
    box = Box(
        PrivateKey(
            settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_secret_key'], encoder=encoder
        ),
        PublicKey(
            settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_payments_public_key'], encoder=encoder
        )
    )
    return box.encrypt(message, encoder=encoder)
示例#21
0
def createMsgA(trec, msgC):
    MSTID = rrid.randomize(trec["STID"].decode("hex"))
    msgB = netstring(MSTID) + msgC

    privkey1 = PrivateKey.generate()
    pubkey1 = privkey1.public_key.encode()
    assert len(pubkey1) == 32
    transport_pubkey = trec["transport_pubkey"].decode("hex")
    transport_box = Box(privkey1, PublicKey(transport_pubkey))
    boxed = transport_box.encrypt(msgB, os.urandom(Box.NONCE_SIZE))

    msgA = b"".join([b"a0:", pubkey1, boxed])
    return msgA
示例#22
0
 def create_properties(self):
     try:
         rk = os.environ.get('KNOWN_RK') or \
              "d90cacd31e22c63ce99f062e88d6d2734e944e8d3dac895a67472701b6c55c7e"
         uk = os.environ.get('KNOWN_UK') or \
             "1a41da8aa64dc15e26e8ca787d35d559c10774d4a8e8c373418a0b0862f6567c"
     except:
         rk = 'd90cacd31e22c63ce99f062e88d6d2734e944e8d3dac895a67472701b6c55c7e'
         uk = '1a41da8aa64dc15e26e8ca787d35d559c10774d4a8e8c373418a0b0862f6567c'
     self.rk = PrivateKey(private_key=bytes(rk, 'utf-8'),
                          encoder=nacl.encoding.HexEncoder)
     self.uk = PublicKey(public_key=bytes(uk, 'utf-8'),
                         encoder=nacl.encoding.HexEncoder)
示例#23
0
    def test_login_with_wrong_password(self):
        """
        Ensure we cannot login with wrong authkey
        """

        # our public / private key box
        box = PrivateKey.generate()

        # our hex encoded public / private keys
        user_session_private_key_hex = box.encode(
            encoder=nacl.encoding.HexEncoder).decode()
        user_session_public_key_hex = box.public_key.encode(
            encoder=nacl.encoding.HexEncoder).decode()

        server_crypto_box = Box(
            PrivateKey(user_session_private_key_hex,
                       encoder=nacl.encoding.HexEncoder),
            PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder))

        login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
        encrypted = server_crypto_box.encrypt(
            json.dumps({
                'username':
                self.test_username,
                'authkey':
                make_password(
                    binascii.hexlify(os.urandom(
                        settings.AUTH_KEY_LENGTH_BYTES)).decode()),
            }).encode("utf-8"), login_info_nonce)
        login_info_encrypted = encrypted[len(login_info_nonce):]

        data = {
            'login_info':
            nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(),
            'login_info_nonce':
            nacl.encoding.HexEncoder.encode(login_info_nonce).decode(),
            'public_key':
            user_session_public_key_hex,
        }

        url = reverse('authentication_login')

        models.Token.objects.all().delete()

        response = self.client.post(url, data)

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(response.data.get('non_field_errors'),
                         [u'USERNAME_OR_PASSWORD_WRONG'])

        self.assertEqual(models.Token.objects.count(), 0)
示例#24
0
    def rpc_complete_order(self, sender, pubkey, encrypted):
        try:
            box = Box(PrivateKey(self.signing_key.encode(nacl.encoding.RawEncoder)), PublicKey(pubkey))
            order = box.decrypt(encrypted)
            c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict),
                         testnet=self.multiplexer.testnet)

            contract_id = c.accept_receipt(self.multiplexer.ws, self.multiplexer.blockchain)
            self.router.addContact(sender)
            self.log.info("received receipt for order %s" % contract_id)
            return ["True"]
        except Exception:
            self.log.error("unable to parse receipt from %s" % sender)
            return ["False"]
    def recv_hello_response(self, body):
        hello = HelloResponse()
        hello.parse_from_bytes(body)

        signed_data = HelloSignedData()
        signed_data.parse_from_bytes(hello.signedData)

        self.secure = True
        self.pub_key = PublicKey(signed_data.serverPublicKey)
        self.box = Box(self.priv_key, self.pub_key)

        # please forgive me for writing this monstrosity
        shell = InteractiveShellEmbed()
        threading.Thread(target=shell, kwargs={"local_ns": {"client": self}}).start()
示例#26
0
def _get_public_key():
    """
    Get the configured PublicKey instance

    Returns:
        PublicKey:
            the public key as configured in settings
    """
    if not settings.EXAMS_AUDIT_NACL_PUBLIC_KEY:
        raise ImproperlyConfigured(
            "EXAMS_AUDIT_NACL_PUBLIC_KEY is required but not set"
        )

    return PublicKey(settings.EXAMS_AUDIT_NACL_PUBLIC_KEY, encoder=Base64Encoder)
示例#27
0
 def rpc_refund(self, sender, pubkey, encrypted):
     try:
         box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey))
         refund = box.decrypt(encrypted)
         refund_json = json.loads(refund, object_pairs_hook=OrderedDict)
         c = Contract(self.db, hash_value=unhexlify(refund_json["refund"]["order_id"]),
                      testnet=self.multiplexer.testnet)
         c.process_refund(refund_json, self.multiplexer.blockchain, self.get_notification_listener())
         self.router.addContact(sender)
         self.log.info("order %s refunded by vendor" % refund_json["refund"]["order_id"])
         return ["True"]
     except Exception, e:
         self.log.error("unable to parse refund message from %s" % sender)
         return [e.message]
示例#28
0
def _do_connect(config: Config) -> SocketPort:
    if (not config.server_verify_key or not config.signing_key
            or not config.server_address):
        print(
            "Using permuter@home requires someone to give you access to a central -J server.\n"
            "Run `./pah.py setup` to set this up.")
        print()
        sys.exit(1)

    host, port_str = config.server_address.split(":")
    try:
        sock = socket.create_connection((host, int(port_str)))
    except ConnectionRefusedError:
        raise EOFError("connection refused") from None
    except socket.gaierror as e:
        raise EOFError(f"DNS lookup failed: {e}") from None
    except Exception as e:
        raise EOFError("unable to connect: " +
                       exception_to_string(e)) from None

    # Send over the protocol version and an ephemeral encryption key which we
    # are going to use for all communication.
    ephemeral_key = PrivateKey.generate()
    ephemeral_key_data = ephemeral_key.public_key.encode()
    sock.sendall(b"p@h0" + ephemeral_key_data)

    # Receive the server's encryption key, plus a signature of it and our own
    # ephemeral key -- this guarantees that we are talking to the server and
    # aren't victim to a replay attack. Use it to set up a communication port.
    msg = socket_read_fixed(sock, 32 + 64)
    server_enc_key_data = msg[:32]
    config.server_verify_key.verify(
        b"HELLO:" + ephemeral_key_data + server_enc_key_data, msg[32:])
    box = Box(ephemeral_key, PublicKey(server_enc_key_data))
    port = SocketPort(sock, box, "controller", is_client=True)

    # Use the encrypted port to send over our public key, proof that we are
    # able to sign new things with it, as well as permuter version.
    signature: bytes = config.signing_key.sign(b"WORLD:" +
                                               server_enc_key_data).signature
    port.send(config.signing_key.verify_key.encode() + signature +
              struct.pack(">I", PERMUTER_VERSION))

    # Get an acknowledgement that the server wants to talk to us.
    obj = port.receive_json()

    if "message" in obj:
        print(obj["message"])

    return port
示例#29
0
    def connect(self, path=None):
        if path is None:
            path = Connection.get_socket_path()

        self.socket.connect(path)
        message = json.dumps(self.change_public_keys())
        self.socket.sendall(message.encode("utf-8"))
        response = self.get_unencrypted_response()
        if not response["success"]:
            raise ResponseUnsuccesfulException
        self.box = Box(self.private_key,
                       PublicKey(base64.b64decode(response["publicKey"])))
        self.nonce = (int.from_bytes(self.nonce, "big") + 1).to_bytes(
            24, "big")
示例#30
0
def test_sealed_box_encryption(privalice, pubalice, plaintext, _encrypted):
    pubalice = PublicKey(pubalice, encoder=HexEncoder)
    privalice = PrivateKey(privalice, encoder=HexEncoder)

    box = SealedBox(pubalice)
    encrypted = box.encrypt(binascii.unhexlify(plaintext), encoder=HexEncoder,)

    assert encrypted != _encrypted
    # since SealedBox.encrypt uses an ephemeral sender's keypair

    box2 = SealedBox(privalice)
    decrypted = box2.decrypt(encrypted, encoder=HexEncoder,)
    assert binascii.hexlify(decrypted) == plaintext
    assert bytes(box) == bytes(box2)
示例#31
0
    def test_msgA(self):
        nA, nB, entA, entB = self.make_nodes()
        msgC = "msgC"

        trec = json.loads(entA["their_channel_record_json"])["transports"][0]
        msgA = createMsgA(trec, msgC)

        pubkey1_s, boxed = parseMsgA(msgA)
        tpriv = self.tport2[0]["privkey"]
        b = Box(tpriv, PublicKey(pubkey1_s))
        msgB = b.decrypt(boxed)

        MSTID, msgC2 = parseMsgB(msgB)
        self.failUnlessEqual(msgC, msgC2)
示例#32
0
    def send_message(self,
                     receiving_node,
                     public_key,
                     message_type,
                     message,
                     subject=None,
                     store_only=False):
        """
        Sends a message to another node. If the node isn't online it
        will be placed in the dht for the node to pick up later.
        """
        pro = Profile(self.db).get()
        p = objects.Plaintext_Message()
        p.sender_guid = self.kserver.node.id
        p.signed_pubkey = self.kserver.node.signed_pubkey
        p.encryption_pubkey = PrivateKey(
            self.signing_key.encode()).public_key.encode()
        p.type = message_type
        p.message = message
        if subject is not None:
            p.subject = subject
        if pro.handle:
            p.handle = pro.handle
        if pro.avatar_hash:
            p.avatar_hash = pro.avatar_hash
        p.timestamp = int(time.time())
        signature = self.signing_key.sign(p.SerializeToString())[:64]
        p.signature = signature

        skephem = PrivateKey.generate()
        pkephem = skephem.public_key.encode(nacl.encoding.RawEncoder)
        box = Box(skephem, PublicKey(public_key, nacl.encoding.HexEncoder))
        nonce = nacl.utils.random(Box.NONCE_SIZE)
        ciphertext = box.encrypt(p.SerializeToString(), nonce)

        def get_response(response):
            if not response[0]:
                ciphertext = box.encrypt(p.SerializeToString().encode("zlib"),
                                         nonce)
                self.kserver.set(digest(receiving_node.id), pkephem,
                                 ciphertext)

        self.log.info("sending encrypted message to %s" %
                      receiving_node.id.encode("hex"))
        if not store_only:
            self.protocol.callMessage(receiving_node, pkephem,
                                      ciphertext).addCallback(get_response)
        else:
            get_response([False])
 def identify(self, data):
     if not self.disable_encryption:
         from nacl.public import PublicKey
     cmd_data = data["data"]
     try:
         self.name = cmd_data["kwargs"]["name"]
         print(cmd_data["kwargs"]["public_key"],len(cmd_data["kwargs"]["public_key"]))
         if not self.disable_encryption:
             self.public_key = PublicKey(bytes([int(x) for x in base64.b64decode(cmd_data["kwargs"]["public_key"]).decode('utf-8').split(',')]))
         self.identified = True
         self.sendMsg(
             commandmessage(sender="server", cmd="set_time", time=self.server.t0)
         )
     except Exception as e:
         self.server.logger.exception(e)
示例#34
0
class TestPublicKey:
    def test_equal_keys_have_equal_hashes(self):
        k1 = PublicKey(b"\x00" * crypto_box_PUBLICKEYBYTES)
        k2 = PublicKey(b"\x00" * crypto_box_PUBLICKEYBYTES)
        assert hash(k1) == hash(k2)
        assert id(k1) != id(k2)

    def test_equal_keys_are_equal(self):
        k1 = PublicKey(b"\x00" * crypto_box_PUBLICKEYBYTES)
        k2 = PublicKey(b"\x00" * crypto_box_PUBLICKEYBYTES)
        assert_equal(k1, k1)
        assert_equal(k1, k2)

    @pytest.mark.parametrize(
        "k2",
        [
            b"\x00" * crypto_box_PUBLICKEYBYTES,
            PublicKey(b"\x01" * crypto_box_PUBLICKEYBYTES),
            PublicKey(b"\x00" * (crypto_box_PUBLICKEYBYTES - 1) + b"\x01"),
        ],
    )
    def test_different_keys_are_not_equal(self, k2):
        k1 = PublicKey(b"\x00" * crypto_box_PUBLICKEYBYTES)
        assert_not_equal(k1, k2)
示例#35
0
    def encrypt(self, packetID, payload):
        if packetID == 10100:

            return payload

        elif packetID == 10101:

            self.encryptNonce = Nonce()
            self.Nonce        = Nonce(clientKey=self.pk, serverKey=self.serverKey)
            self.sharedKey    = Box(self.sk, PublicKey(self.serverKey))

            return bytes(self.pk) + self.encryptPacket(self.sessionKey + bytes(self.encryptNonce) + payload, self.Nonce)

        else:
            return self.encryptPacket(payload)
示例#36
0
 def __init__(self, iid, db, manager):
     self.iid = iid
     self.db = db
     self.manager = manager
     c = self.db.execute("SELECT petname, inviteID, inviteKey," # 0,1,2
                         " theirTempPubkey," # 3
                         " nextExpectedMessage," # 4
                         " myMessages," # 5
                         " theirMessages" # 6
                         " FROM invitations WHERE id = ?", (iid,))
     res = c.fetchone()
     if not res:
         raise KeyError("no pending Invitation for '%d'" % iid)
     self.petname = res[0]
     self.inviteID = res[1]
     self.inviteKey = SigningKey(res[2].decode("hex"))
     self.theirTempPubkey = None
     if res[3]:
         self.theirTempPubkey = PublicKey(res[3].decode("hex"))
     self.nextExpectedMessage = int(res[4])
     self.myMessages = splitMessages(res[5])
     self.theirMessages = splitMessages(res[6])
示例#37
0
    def on_post(self, req, resp):
        configuration = req.context['configuration']

        if req.content_length:
            data = json.load(req.bounded_stream)
        else:
            raise Exception("No data.")

        if 'public_key' not in data:
            raise Exception("No public key.")

        if 'captcha' not in data:
            raise Exception("No captcha.")

        if 'uuid' not in data['captcha']:
            raise Exception("No captcha UUID.")

        if 'encrypted_answer' not in data['captcha']:
            raise Exception("No captcha encrypted answer.")

        if 'nonce' not in data['captcha']:
            raise Exception("No captcha nonce.")

        # Decrypt captcha answer

        user_public_key = PublicKey(data['public_key'].encode('utf-8'), encoder = nacl.encoding.Base64Encoder)

        captcha_encrypted_answer = base64.b64decode(data['captcha']['encrypted_answer'].encode('utf-8'))
        captcha_nonce = base64.b64decode(data['captcha']['nonce'].encode('utf-8'))

        box = Box(configuration['server_key_pair'], user_public_key)
        captcha_answer = box.decrypt(captcha_encrypted_answer, captcha_nonce).decode('utf-8').lower()

        # Get captcha from database

        db_session = req.context['db_session']
        captcha = db_session.query(db.Captcha).filter(db.Captcha.uuid == data['captcha']['uuid']).first()

        # Whatever happens, delete the captcha from database
        db_session.delete(captcha)
        db_session.commit()

        # Check the IP hash of the user who requested the captcha matches the current client's IP hash
        ip_address_hash = nacl.hash.sha256(str.encode(captcha.uuid + req.remote_addr), encoder = nacl.encoding.RawEncoder)
        user_agent_hash = nacl.hash.sha256(str.encode(captcha.uuid + req.user_agent), encoder = nacl.encoding.RawEncoder)
        answer_hash = nacl.hash.sha256(str.encode(captcha.uuid + captcha_answer), encoder = nacl.encoding.RawEncoder)

        if (ip_address_hash != captcha.ip_address_hash) or (user_agent_hash != captcha.user_agent_hash):
            raise Exception("Captcha answer incorrect.")

        # Check the captcha answer
        if captcha.answer_hash != answer_hash:
            raise Exception("Captcha answer incorrect.")

        # Create new user
        user = db.User(
            public_key = user_public_key.encode(nacl.encoding.RawEncoder)
        )

        db_session.add(user)
        db_session.commit()

        resp.status = falcon.HTTP_201
        resp.body = json.dumps({})
示例#38
0
# Info
ServerInfo = '{"Name":"Example","Url":"https://noob.example.com/sendOOB"}'
PeerInfo = '{"Make":"Acme","Type":"None","Serial":"DU-9999","SSID":"Noob1",\
    "BSSID":"6c:19:8f:83:c2:80"}'

# KeyingMode
KeyingMode = 2

# SleepTime
SleepTime = 60


################################################################################
############################## CALCULATED  VALUES ##############################
## Load peer and server public keys
PK_peer = PublicKey(bytes.fromhex(PKp))
PK_server = PublicKey(bytes.fromhex(PKs))
#PK2_peer = PublicKey(bytes.fromhex(PKp))
#PK2_server = PublicKey(bytes.fromhex(PKs))

# Peer and server public keys - base64 encoded
PKp_b64 = base64url_encode(bytes.fromhex(PKp)).decode().strip('=')
PKs_b64 = base64url_encode(bytes.fromhex(PKs)).decode().strip('=')
#PKp2_b64 = base64url_encode(bytes.fromhex(PKp2)).decode().strip('=')
#PKs2_b64 = base64url_encode(bytes.fromhex(PKs2)).decode().strip('=')

# Peer and server public keys - jwk formatted
PKp_full = loads('{"kty":"EC", "crv":"Curve25519", "x":""}',
    object_pairs_hook=OrderedDict)
PKs_full = loads('{"kty":"EC", "crv":"Curve25519", "x":""}',
    object_pairs_hook=OrderedDict)
示例#39
0
class Invitation:
    # This has a brief lifetime: one is created in response to the rendezvous
    # client discovering new messages for us, used for one reactor tick, then
    # dereferenced. It holds onto a few values during that tick (which may
    # process multiple messages for a single invitation, e.g. A's second poll
    # will receive both B-m1 and B-m2 together). But all persistent state
    # beyond that one tick is stored in the database.
    def __init__(self, iid, db, manager):
        self.iid = iid
        self.db = db
        self.manager = manager
        c = self.db.execute("SELECT petname, inviteID, inviteKey," # 0,1,2
                            " theirTempPubkey," # 3
                            " nextExpectedMessage," # 4
                            " myMessages," # 5
                            " theirMessages" # 6
                            " FROM invitations WHERE id = ?", (iid,))
        res = c.fetchone()
        if not res:
            raise KeyError("no pending Invitation for '%d'" % iid)
        self.petname = res[0]
        self.inviteID = res[1]
        self.inviteKey = SigningKey(res[2].decode("hex"))
        self.theirTempPubkey = None
        if res[3]:
            self.theirTempPubkey = PublicKey(res[3].decode("hex"))
        self.nextExpectedMessage = int(res[4])
        self.myMessages = splitMessages(res[5])
        self.theirMessages = splitMessages(res[6])

    def getAddressbookID(self):
        c = self.db.execute("SELECT addressbook_id FROM invitations"
                            " WHERE id = ?", (self.iid,))
        return c.fetchone()[0]

    def getMyTempPrivkey(self):
        c = self.db.execute("SELECT myTempPrivkey FROM invitations"
                            " WHERE id = ?", (self.iid,))
        return PrivateKey(c.fetchone()[0].decode("hex"))

    def getMySigningKey(self):
        c = self.db.execute("SELECT mySigningKey FROM invitations"
                            " WHERE id = ?", (self.iid,))
        return SigningKey(c.fetchone()[0].decode("hex"))

    def getMyPublicChannelRecord(self):
        c = self.db.execute("SELECT my_channel_record FROM invitations"
                            " WHERE id = ?", (self.iid,))
        return c.fetchone()[0]

    def getMyPrivateChannelData(self):
        c = self.db.execute("SELECT my_private_channel_data FROM invitations"
                            " WHERE id = ?", (self.iid,))
        return json.loads(c.fetchone()[0])


    def sendFirstMessage(self):
        pub = self.getMyTempPrivkey().public_key.encode()
        self.send("i0:m1:"+pub)
        self.db.update("UPDATE invitations SET myMessages=? WHERE id=?",
                       (",".join(self.myMessages), self.iid),
                       "invitations", self.iid)
        # that will be commited by our caller

    def processMessages(self, messages):
        # These messages are neither version-checked nor signature-checked.
        # Also, we may have already processed some of them.
        #print "processMessages", messages
        #print " my", self.myMessages
        #print " theirs", self.theirMessages
        assert isinstance(messages, set), type(messages)
        assert None not in messages, messages
        assert None not in self.myMessages, self.myMessages
        assert None not in self.theirMessages, self.theirMessages
        # Send anything that didn't make it to the server. This covers the
        # case where we commit our outbound message in send() but crash
        # before finishing delivery.
        for m in self.myMessages - messages:
            #print "resending", m
            self.manager.sendToAll(self.inviteID, m)

        newMessages = messages - self.myMessages - self.theirMessages
        #print " %d new messages" % len(newMessages)
        if not newMessages:
            print " huh, no new messages, stupid rendezvous client"

        # check signatures, extract bodies. invalid messages kill the channel
        # and the invitation. MAYBE TODO: lose the one channel, keep using
        # the others.
        bodies = set()
        for m in newMessages:
            #print " new inbound message", m
            try:
                if not m.startswith("r0:"):
                    print "unrecognized rendezvous message prefix"
                if not VALID_MESSAGE.search(m):
                    raise CorruptChannelError()
                m = m[len("r0:"):].decode("hex")
                bodies.add(self.inviteKey.verify_key.verify(m))
            except (BadSignatureError, CorruptChannelError) as e:
                print "channel %s is corrupt" % self.inviteID
                if isinstance(e, BadSignatureError):
                    print " (bad sig)"
                self.unsubscribe(self.inviteID)
                # TODO: mark invitation as failed, destroy it
                return

        #print " new inbound bodies:", ", ".join([repr(b[:10])+" ..." for b in bodies])

        # these handlers will update self.myMessages with sent messages, and
        # will increment self.nextExpectedMessage. We can handle multiple
        # (sequential) messages in a single pass.
        if self.nextExpectedMessage == 1:
            self.findPrefixAndCall("i0:m1:", bodies, self.processM1)
            # no elif here: self.nextExpectedMessage may have incremented
        if self.nextExpectedMessage == 2:
            self.findPrefixAndCall("i0:m2:", bodies, self.processM2)
        if self.nextExpectedMessage == 3:
            self.findPrefixAndCall("i0:m3:", bodies, self.processM3)

        self.db.update("UPDATE invitations SET"
                       "  myMessages=?,"
                       "  theirMessages=?,"
                       "  nextExpectedMessage=?"
                       " WHERE id=?",
                       (",".join(self.myMessages),
                        ",".join(self.theirMessages | newMessages),
                        self.nextExpectedMessage,
                        self.iid),
                       "invitations", self.iid)
        #print " db.commit"
        self.db.commit()

    def findPrefixAndCall(self, prefix, bodies, handler):
        for msg in bodies:
            if msg.startswith(prefix):
                return handler(msg[len(prefix):])
        return None

    def send(self, msg, persist=True):
        #print "send", repr(msg[:10]), "..."
        signed = "r0:%s" % self.inviteKey.sign(msg).encode("hex")
        if persist: # m4-destroy is not persistent
            self.myMessages.add(signed) # will be persisted by caller
            # This will be added to the DB, and committed, by our caller, to
            # get it into the same transaction as the update to which inbound
            # messages we've processed.
        assert VALID_MESSAGE.search(signed), signed
        self.manager.sendToAll(self.inviteID, signed)

    def processM1(self, msg):
        #print "processM1", self.petname
        self.theirTempPubkey = PublicKey(msg)
        self.db.update("UPDATE invitations SET theirTempPubkey=?"
                       " WHERE id=?",
                       (self.theirTempPubkey.encode(Hex), self.iid),
                       "invitations", self.iid)
        # theirTempPubkey will committed by our caller, in the same txn as
        # the message send

        my_privkey = self.getMyTempPrivkey()
        my_channel_record = self.getMyPublicChannelRecord()
        b = Box(my_privkey, self.theirTempPubkey)
        signedBody = b"".join([self.theirTempPubkey.encode(),
                               my_privkey.public_key.encode(),
                               my_channel_record.encode("utf-8")])
        my_sign = self.getMySigningKey()
        body = b"".join([b"i0:m2a:",
                         my_sign.verify_key.encode(),
                         my_sign.sign(signedBody)
                         ])
        nonce = os.urandom(Box.NONCE_SIZE)
        nonce_and_ciphertext = b.encrypt(body, nonce)
        #print "ENCRYPTED n+c", len(nonce_and_ciphertext), nonce_and_ciphertext.encode("hex")
        #print " nonce", nonce.encode("hex")
        msg2 = "i0:m2:"+nonce_and_ciphertext
        self.send(msg2)
        self.nextExpectedMessage = 2

    def processM2(self, msg):
        #print "processM2", repr(msg[:10]), "...", self.petname
        assert self.theirTempPubkey
        nonce_and_ciphertext = msg
        my_privkey = self.getMyTempPrivkey()
        b = Box(my_privkey, self.theirTempPubkey)
        #nonce = msg[:Box.NONCE_SIZE]
        #ciphertext = msg[Box.NONCE_SIZE:]
        #print "DECRYPTING n+ct", len(msg), msg.encode("hex")
        body = b.decrypt(nonce_and_ciphertext)
        if not body.startswith("i0:m2a:"):
            raise ValueError("expected i0:m2a:, got '%r'" % body[:20])
        verfkey_and_signedBody = body[len("i0:m2a:"):]
        theirVerfkey = VerifyKey(verfkey_and_signedBody[:32])
        signedBody = verfkey_and_signedBody[32:]
        body = theirVerfkey.verify(signedBody)
        check_myTempPubkey = body[:32]
        check_theirTempPubkey = body[32:64]
        their_channel_record_json = body[64:].decode("utf-8")
        #print " binding checks:"
        #print " check_myTempPubkey", check_myTempPubkey.encode("hex")
        #print " my real tempPubkey", my_privkey.public_key.encode(Hex)
        #print " check_theirTempPubkey", check_theirTempPubkey.encode("hex")
        #print " first theirTempPubkey", self.theirTempPubkey.encode(Hex)
        if check_myTempPubkey != my_privkey.public_key.encode():
            raise ValueError("binding failure myTempPubkey")
        if check_theirTempPubkey != self.theirTempPubkey.encode():
            raise ValueError("binding failure theirTempPubkey")

        them = json.loads(their_channel_record_json)
        me = self.getMyPrivateChannelData()
        addressbook_id = self.db.insert(
            "INSERT INTO addressbook"
            " (petname, acked,"
            "  next_outbound_seqnum, my_signkey,"
            "  their_channel_record_json,"
            "  my_CID_key, next_CID_token,"
            "  highest_inbound_seqnum,"
            "  my_old_channel_privkey, my_new_channel_privkey,"
            "  they_used_new_channel_key, their_verfkey)"
            " VALUES (?,?, "
            "         ?,?,"
            "         ?,"
            "         ?,?," # my_CID_key, next_CID_token
            "         ?,"   # highest_inbound_seqnum
            "         ?,?,"
            "         ?,?)",
            (self.petname, 0,
             1, me["my_signkey"],
             json.dumps(them),
             me["my_CID_key"], None,
             0,
             me["my_old_channel_privkey"],
             me["my_new_channel_privkey"],
             0, theirVerfkey.encode(Hex) ),
            "addressbook")
        self.db.update("UPDATE invitations SET addressbook_id=?"
                       " WHERE id=?", (addressbook_id, self.iid),
                       "invitations", self.iid)

        msg3 = "i0:m3:ACK-"+os.urandom(16)
        self.send(msg3)
        self.nextExpectedMessage = 3

    def processM3(self, msg):
        #print "processM3", repr(msg[:10]), "..."
        if not msg.startswith("ACK-"):
            raise ValueError("bad ACK")
        cid = self.getAddressbookID()
        self.db.update("UPDATE addressbook SET acked=1 WHERE id=?", (cid,),
                       "addressbook", cid )
        self.db.delete("DELETE FROM invitations WHERE id=?", (self.iid,),
                       "invitations", self.iid)

        # we no longer care about the channel
        msg4 = "i0:destroy:"+os.urandom(16)
        self.send(msg4, persist=False)
        self.manager.unsubscribe(self.inviteID)