Exemplo n.º 1
0
    def crypto_initiate(self, cookiepacket) -> bytes:
        """ Validate the cookie packet and create the corresponding
        initate packet consisting of:

        * 8 bytes: the ASCII bytes "oqQN2kaI".
        * 96 bytes: the server's cookie.
        * 8 bytes: a client-selected compressed nonce in little-endian form.
                  This compressed nonce is implicitly prefixed by
                  "splonebox-client" to form a 24-byte nonce.
        * 144 bytes: a cryptographic box encrypted and authenticated to the
                    server's short-term public key S' from the client's
                    short-term public key C' using this 24-byte nonce. The
                    (96+M)-byte plaintext inside the box has the following
                    contents:
          * 32 bytes: the client's long-term public key C.
          * 16 bytes: a client-selected compressed nonce in little-endian
                      form. This compressed nonce is implicitly prefixed by
                      "splonePV" to form a 24-byte nonce.
          * 80 bytes: a cryptographic box encrypted and authenticated to the
                      server's long-term public key S from the client's
                      long-term public key C using this 24-byte nonce. The
                      32-byte plaintext inside the box has the following
                      contents:
              * 32 bytes: the client's short-term public key C'.
              * 32 bytes: server's short term public key S'

        cookiepacket -- the cookie packet sent by server

        :return: client initiate packet
        """
        cookie = self._verify_cookiepacket(cookiepacket)
        vouch_payload = b"".join(
            [self.clientshorttermpk, self.servershorttermpk])
        vouch_nonce = self.safenonce()
        vouch_nonce_expanded = struct.pack("<8s16s", b"splonePV", vouch_nonce)

        vouch_box = libnacl.crypto_box(vouch_payload, vouch_nonce_expanded,
                                       self.serverlongtermpk,
                                       self.clientlongtermsk)

        payload = b"".join([self.clientlongtermpk, vouch_nonce, vouch_box])

        self.crypto_nonce_update()

        payload_nonce = struct.pack("<16sQ", b"splonebox-client", self.nonce)
        payload_box = libnacl.crypto_box(payload, payload_nonce,
                                         self.servershorttermpk,
                                         self.clientshorttermsk)

        identifier = struct.pack("<8s", b"oqQN2kaI")

        nonce = struct.pack("<Q", self.nonce)
        initiatepacket = b"".join([identifier, cookie, nonce, payload_box])

        self.crypto_established.set()
        return initiatepacket
Exemplo n.º 2
0
    def test_040_verify_cookiepacket(self):
        """ Check whether cookie is properly extraced. """
        identifier = struct.pack("<8s", b"rZQTd2nC")
        nonce = libnacl.randombytes(16)
        nonce_expanded = struct.pack("<8s16s", b"splonePK", nonce)

        cookie = libnacl.randombytes(96)
        payload = b''.join([self.servershorttermpk, cookie])
        box = libnacl.crypto_box(payload, nonce_expanded,
                                 self.crypt.clientshorttermpk,
                                 self.serverlongtermsk)

        # good case
        data = b''.join([identifier, nonce, box])
        cookie_extracted = self.crypt._verify_cookiepacket(data)
        self.assertEqual(cookie, cookie_extracted)

        # too short
        self.assertRaises(InvalidPacketException,
                          self.crypt._verify_cookiepacket, data[:167])

        # message has illegal identifier
        data = b''.join([struct.pack("<8s", b'foobar'), nonce, box])
        self.assertRaises(InvalidPacketException,
                          self.crypt._verify_cookiepacket, data)

        # manipulated payload
        data = b''.join([identifier, nonce, libnacl.randombytes(len(box))])
        self.assertRaises(InvalidPacketException,
                          self.crypt._verify_cookiepacket, data)
Exemplo n.º 3
0
    def crypto_hello(self) -> bytes:
        """Create a client tunnel packet consisting of:
        * 8 bytes: the ASCII bytes "oqQN2kaH"
        * 32 bytes: client's short-term public key C'
        * 64 bytes: all zero
        * 8 bytes: a client-selected compressed nonce in little-endian
                   form. This compressed nonce is implicitly prefixed by
                   "splonebox-client" to form a 24-byte nonce
        * 80 bytes: a cryptographic box encrypted and authenticated to the
                    server's long-term public key S from the client's short-term
                    public key C' using this 24-byte nonce. The 64-byte
                    plaintext inside the box has the following contents:
            * 64 bytes: all zero

        :return: client hello packet
        """
        self.crypto_nonce_update()

        identifier = struct.pack("<8s", b"oqQN2kaH")
        nonce = struct.pack("<16sQ", b"splonebox-client-H", self.nonce)
        zeros = bytearray(64)

        self.clientshorttermpk, \
            self.clientshorttermsk = libnacl.crypto_box_keypair()
        box = libnacl.crypto_box(zeros, nonce, self.serverlongtermpk,
                                 self.clientshorttermsk)

        nonce = struct.pack("<Q", self.nonce)

        return b"".join(
            [identifier, self.clientshorttermpk, zeros, nonce, box])
Exemplo n.º 4
0
def confirm(request, addr, publicKey, password):
    her_public = b64decode(request['pk'][0])
    response = {
        'credentials': {
            ('%s:%s' % addr): {
                'publicKey': publicKey,
                'password': password
            }
        }
    }
    response = json.dumps(response)

    my_public, my_private = libnacl.crypto_box_keypair()
    nonce = libnacl.utils.rand_nonce()
    encrypted = b64encode(
        libnacl.crypto_box(response, nonce, her_public, my_private))

    offer = {
        'type': 'credentials',
        'interface': 'udp',
        'message': encrypted,
        'n': b64encode(nonce),
        'pk': b64encode(my_public),
        'wrbtVersion': WRBT_VERSION
    }

    return PREFIX + '#' + urlencode(offer)
Exemplo n.º 5
0
    def crypto_write(self, data: bytes) -> bytes:
        """Create a client message packet consisting of:
        * 8 bytes: the ASCII bytes "oqQN2kaM"
        * 8 bytes: a client-selected compressed nonce in little-endian form.
                   This compressed nonce is implicitly prefixed by
                   "splonebox-server" to form a 24-byte nonce.
        * 24 bytes: a cryptographic box encrypted and authenticated to the
                    client's short-term public key C' from the server's
                    short-term public key S' using this 24-byte nonce.
                    The M-byte plaintext inside the box has
                    the following contents:
            * 8 bytes: length
        * n bytes: a cryptographic box encrypted and authenticated to the
                    client's short-term public key C' from the server's
                    short-term public key S' using this 24-byte nonce. The
                    plaintext inside the box has the following contents:
            * m bytes: data

        NOTE: This function NOT thread safe.
              The nonce needs to be updated for every individual message
              AFTER it was sent.

        :return: client message packet
        :raises: :CryptError on failure
        """
        self.crypto_nonce_update()
        message_nonce = struct.pack("<Q", self.nonce)

        length = struct.pack("<Q", 56 + len(data))
        length_nonce = struct.pack("<16sQ", b"splonebox-client", self.nonce)

        length_boxed = libnacl.crypto_box(length, length_nonce,
                                          self.servershorttermpk,
                                          self.clientshorttermsk)

        self.crypto_nonce_update()
        identifier = struct.pack("<8s", b"oqQN2kaM")
        data_nonce = struct.pack("<16sQ", b"splonebox-client", self.nonce)
        box = libnacl.crypto_box(data, data_nonce, self.servershorttermpk,
                                 self.clientshorttermsk)

        return b"".join([identifier, message_nonce, length_boxed, box])
Exemplo n.º 6
0
 def test_box(self):
     msg = b'Are you suggesting coconuts migrate?'
     # run 1
     nonce1 = libnacl.utils.rand_nonce()
     pk1, sk1 = libnacl.crypto_box_keypair()
     pk2, sk2 = libnacl.crypto_box_keypair()
     enc_msg = libnacl.crypto_box(msg, nonce1, pk2, sk1)
     self.assertNotEqual(msg, enc_msg)
     clear_msg = libnacl.crypto_box_open(enc_msg, nonce1, pk1, sk2)
     self.assertEqual(clear_msg, msg)
     # run 2
     nonce2 = libnacl.utils.rand_nonce()
     pk3, sk3 = libnacl.crypto_box_keypair()
     pk4, sk4 = libnacl.crypto_box_keypair()
     enc_msg2 = libnacl.crypto_box(msg, nonce2, pk4, sk3)
     self.assertNotEqual(msg, enc_msg2)
     clear_msg2 = libnacl.crypto_box_open(enc_msg2, nonce2, pk3, sk4)
     self.assertEqual(clear_msg2, msg)
     # Check bits
     self.assertNotEqual(nonce1, nonce2)
     self.assertNotEqual(enc_msg, enc_msg2)
Exemplo n.º 7
0
    def encrypt_to(self, message, recipients):
        """Encrypt a secret message to ``recipients`` using our private key."""
        nonce = os.urandom(24)
        key = os.urandom(32)
        secret = dict(
            sender=json_bytes(self.publicKey),
            nonce=json_bytes(nonce),
            secret=json_bytes(libnacl.crypto_secretbox(message, nonce, key)),
            keys={},
        )

        print recipients
        for pub in recipients:
            box = libnacl.crypto_box(key, nonce, pub, self.privateKey)
            secret['keys'][json_bytes(pub)] = json_bytes(box)

        return secret
Exemplo n.º 8
0
    def _encryptQuery(self, queryContent, resolverCert, nonce, tcp=False):
        header = resolverCert.clientMagic + self._publicKey + nonce
        requiredSize = len(header) + self.DNSCRYPT_MAC_SIZE + len(queryContent)
        paddingSize = self.DNSCRYPT_PADDED_BLOCK_SIZE - (len(queryContent) % self.DNSCRYPT_PADDED_BLOCK_SIZE)
        # padding size should be DNSCRYPT_PADDED_BLOCK_SIZE <= padding size <= 4096
        if not tcp and requiredSize < self.DNSCRYPT_MIN_UDP_LENGTH:
            paddingSize += self.DNSCRYPT_MIN_UDP_LENGTH - requiredSize
            requiredSize = self.DNSCRYPT_MIN_UDP_LENGTH

        padding = '\x80'
        idx = 0
        while idx < (paddingSize - 1):
            padding = padding + '\x00'
            idx += 1

        data = queryContent + padding
        nonce = nonce + ('\x00'*(self.DNSCRYPT_NONCE_SIZE / 2))
        box = libnacl.crypto_box(data, nonce, resolverCert.publicKey, self._privateKey)
        return header + box
Exemplo n.º 9
0
    def _encryptQuery(self, queryContent, resolverCert, nonce):
        header = resolverCert.clientMagic + self._publicKey + nonce
        requiredSize = len(header) + self.DNSCRYPT_MAC_SIZE + len(queryContent)
        paddingSize = self.DNSCRYPT_PADDED_BLOCK_SIZE - (len(queryContent) % self.DNSCRYPT_PADDED_BLOCK_SIZE)
        # padding size should be DNSCRYPT_PADDED_BLOCK_SIZE <= padding size <= 4096
        if requiredSize < self.DNSCRYPT_MIN_UDP_LENGTH:
            paddingSize += self.DNSCRYPT_MIN_UDP_LENGTH - requiredSize
            requiredSize = self.DNSCRYPT_MIN_UDP_LENGTH

        padding = '\x80'
        idx = 0
        while idx < (paddingSize - 1):
            padding = padding + '\x00'
            idx += 1

        data = queryContent + padding
        nonce = nonce + ('\x00'*(self.DNSCRYPT_NONCE_SIZE / 2))
        box = libnacl.crypto_box(data, nonce, resolverCert.publicKey, self._privateKey)
        return header + box
Exemplo n.º 10
0
    def test_080_crypto_read(self):
        """ Verifying that crypto_read properly handles message packets. """
        nonce_length = 6

        data = libnacl.randombytes(10)
        nonce_expanded = struct.pack("<16sQ", b"splonebox-server",
                                     nonce_length + 2)
        box = libnacl.crypto_box(data, nonce_expanded,
                                 self.crypt.clientshorttermpk,
                                 self.servershorttermsk)

        self.crypt.crypto_verify_length = mock.Mock(return_value=40 + len(box))
        self.crypt._verify_nonce = mock.Mock()

        packet = b''.join([
            bytearray(8),
            struct.pack("<Q", nonce_length),
            bytearray(24), box
        ])
        payload = self.crypt.crypto_read(packet)

        self.assertEqual(payload, data)

        # corrupt box
        packet = b''.join([
            bytearray(8),
            struct.pack("<Q", nonce_length),
            bytearray(24),
            libnacl.randombytes(len(box))
        ])
        self.assertRaises(InvalidPacketException, self.crypt.crypto_read,
                          packet)

        # corrupt nonce
        packet = b''.join(
            [bytearray(8),
             libnacl.randombytes(8),
             bytearray(24), box])
        self.assertRaises(InvalidPacketException, self.crypt.crypto_read,
                          packet)
Exemplo n.º 11
0
    def test_030_verify_length(self):
        """ Verify whether length is properly extraced. """
        payload = libnacl.randombytes(40)
        nonce = self.crypt.last_received_nonce + 2

        nonce_length = struct.pack("<16sQ", b"splonebox-server", nonce)

        length = 40 + len(payload)
        packed_length = struct.pack("<Q", length)
        boxed_length = libnacl.crypto_box(packed_length, nonce_length,
                                          self.crypt.clientshorttermpk,
                                          self.servershorttermsk)

        identifier = struct.pack("<8s", b"rZQTd2nM")
        packed_nonce = struct.pack("<Q", nonce)
        data = b''.join([identifier, packed_nonce, boxed_length, payload])

        # good case
        length_extracted = self.crypt.crypto_verify_length(data)
        self.assertEqual(length, length_extracted)

        # message too short to hold proper length information
        self.assertRaises(InvalidPacketException,
                          self.crypt.crypto_verify_length, data[:39])

        # message has illegal identifier
        data = b''.join([
            struct.pack("<8s", b'foobar'), packed_nonce, boxed_length, payload
        ])
        self.assertRaises(InvalidPacketException,
                          self.crypt.crypto_verify_length, data)

        # length has been altered
        data = b''.join(
            [identifier, packed_nonce,
             libnacl.randombytes(32), payload])
        self.assertRaises(InvalidPacketException,
                          self.crypt.crypto_verify_length, data)
Exemplo n.º 12
0
 def pubkey_encrypt(self,data,nonce,pk,sk):
     return libnacl.crypto_box(data,nonce,pk,sk)
Exemplo n.º 13
0
 def pubkey_encrypt(self, data, nonce, pk, sk):
     return libnacl.crypto_box(data, nonce, pk, sk)
Exemplo n.º 14
0
    def test_crypto_init_functional(self):

        #  generate hello packet
        data = self.crypt.crypto_hello()

        #  extract key and generate cookie response
        extracted_key, = struct.unpack("<32s", data[8:40])

        identifier = struct.pack("<8s", b"rZQTd2nC")
        nonce = libnacl.randombytes(16)
        nonce_expanded = struct.pack("<8s16s", b"splonePK", nonce)

        cookie = libnacl.randombytes(96)
        payload = b''.join([self.servershorttermpk, cookie])
        box = libnacl.crypto_box(payload, nonce_expanded,
                                 extracted_key,
                                 self.serverlongtermsk)

        data = b''.join([identifier, nonce, box])

        # generate initiate-packet from cookiepacket
        self.crypt.crypto_initiate(data)

        # test if the crypto is able to decrypt a server message
        identifier = struct.pack("<8s", b"rZQTd2nM")

        server_nonce = self.crypt.crypto_random_mod(281474976710656)
        server_nonce += 0 if server_nonce % 2 == 0 else 1

        nonce_expanded = struct.pack("<16sQ", b"splonebox-server",
                                     server_nonce)

        payload = libnacl.randombytes(96)
        length = struct.pack("<Q", 56 + len(payload))

        length_boxed = libnacl.crypto_box(length, nonce_expanded,
                                          extracted_key,
                                          self.servershorttermsk)

        server_nonce += 2
        nonce_expanded = struct.pack("<16sQ", b"splonebox-server",
                                     server_nonce)

        box = libnacl.crypto_box(payload, nonce_expanded,
                                 extracted_key,
                                 self.servershorttermsk)

        msg = b"".join([identifier, struct.pack("<Q", server_nonce - 2),
                        length_boxed, box])

        extr = self.crypt.crypto_read(msg)
        self.assertEqual(extr, payload)

        # test if the crypto is able to encrypt a message properly
        payload = libnacl.randombytes(96)
        data = self.crypt.crypto_write(payload)

        identifier, = struct.unpack("<8s", data[:8])
        nonce, = struct.unpack("<Q", data[8:16])
        nonceexpanded = struct.pack("<16sQ", b"splonebox-client", nonce)
        length = libnacl.crypto_box_open(data[16:40], nonceexpanded,
                                         self.crypt.clientshorttermpk,
                                         self.servershorttermsk)
        nonceexpanded = struct.pack("<16sQ", b"splonebox-client", nonce+2)
        plaintext = libnacl.crypto_box_open(data[40:],
                                            nonceexpanded,
                                            self.crypt.clientshorttermpk,
                                            self.servershorttermsk)
        self.assertEqual(plaintext, payload)