Exemple #1
0
    def _set_ciphers(self):
        """Generate out/inbound encryption keys and initialise respective ciphers."""
        outgoing_key = hap_hkdf(self.shared_key, self.CIPHER_SALT, self.OUT_CIPHER_INFO)
        self.out_cipher = ChaCha20Poly1305(outgoing_key)

        incoming_key = hap_hkdf(self.shared_key, self.CIPHER_SALT, self.IN_CIPHER_INFO)
        self.in_cipher = ChaCha20Poly1305(incoming_key)
Exemple #2
0
 def __init__(self, out_key, in_key, nonce_length=8):
     """Initialize a new Chacha20Cipher."""
     self._enc_out = ChaCha20Poly1305(out_key)
     self._enc_in = ChaCha20Poly1305(in_key)
     self._out_counter = 0
     self._in_counter = 0
     self._nonce_length = nonce_length
def setup_keys(shared_key):
    output_key = ChaCha20Poly1305(
        HKDF(hashes.SHA512(), 32,
             b"MediaRemote-Salt", b"MediaRemote-Write-Encryption-Key",
             default_backend()).derive(shared_key))
    input_key = ChaCha20Poly1305(
        HKDF(hashes.SHA512(), 32,
             b"MediaRemote-Salt", b"MediaRemote-Read-Encryption-Key",
             default_backend()).derive(shared_key))
    return output_key, input_key
 def test_buffer_protocol(self, backend):
     key = ChaCha20Poly1305.generate_key()
     chacha = ChaCha20Poly1305(key)
     pt = b"encrypt me"
     ad = b"additional"
     nonce = os.urandom(12)
     ct = chacha.encrypt(nonce, pt, ad)
     computed_pt = chacha.decrypt(nonce, ct, ad)
     assert computed_pt == pt
     chacha2 = ChaCha20Poly1305(bytearray(key))
     ct2 = chacha2.encrypt(bytearray(nonce), pt, ad)
     assert ct2 == ct
     computed_pt2 = chacha2.decrypt(bytearray(nonce), ct2, ad)
     assert computed_pt2 == pt
Exemple #5
0
    def data_received(self, data):
        nonce, ciphertext = data[:12], data[12:]
        plaintext = ChaCha20Poly1305(self._server_read_key).decrypt(
            nonce, ciphertext, b""
        )
        message = plaintext.decode()
        print("Decrypted message from client: {!r}".format(message))
        print("Echo back message: {!r}".format(message))
        reply_nonce = os.urandom(12)
        ciphertext = ChaCha20Poly1305(self._server_write_key).encrypt(
            reply_nonce, plaintext, b""
        )
        self.transport.write(reply_nonce + ciphertext)

        print("Close the client socket")
        self.transport.close()
Exemple #6
0
def encode_private_key(key, passphrase, comment):
    if not passphrase:  # None and empty
        print(f'WARNING: The private key is not encrypted', file=sys.stderr)
        return (MAGIC_WORD + 
	        encode_string(None) + # kdf = none (no kdfoptions)
	        encode_string(None) + # cipher = none
	        encode_string(bytes(key)) + # clear key material
	        (encode_string(comment) if comment is not None else b'')) # optional comment

    # We have a passphrase: we encrypt the private key
    # Ideally, scrypt is chosen over bcrypt or pbkdf2_hmac_sha256
    # But in case there is no support for it, we pick bcrypt
    kdfname = b'scrypt' if scrypt_supported else b'bcrypt'
    saltsize, rounds = get_kdf(kdfname)
    salt = os.urandom(saltsize)
    derived_key = derive_key(kdfname, passphrase, salt, rounds) # dklen = 32
    nonce = os.urandom(12)
    key_bytes = bytes(key)  # Uses RawEncoder
    encrypted_key = ChaCha20Poly1305(derived_key).encrypt(nonce, key_bytes, None)  # No add

    LOG.debug('Derived Key: %s', derived_key.hex().upper())
    LOG.debug('      Nonce: %s', nonce.hex().upper())
    
    return (MAGIC_WORD + 
	    encode_string(kdfname) + # kdf
            encode_string(rounds.to_bytes(4,'big') + salt) + # kdf options
	    encode_string(b'chacha20_poly1305') +  # cipher
	    encode_string(nonce + encrypted_key) +  # encrypted key material
	    (encode_string(comment) if comment is not None else b'')) # optional comment
Exemple #7
0
    def encrypt(message, secret):
        """
        Encrypts a given message data using ``CHACHA20POLY1305``.

        ``SHA256(secret)`` is used as ``key``, and ``0 (12-byte)`` as ``iv``.

        Args:
              message (:obj:`str`): a message to be encrypted. Should be the hex-encoded commitment_tx.
              secret (:obj:`str`): a value to used to derive the encryption key. Should be the dispute txid.

        Returns:
              :obj:`str`: The encrypted data (hex-encoded).

        Raises:
              :obj:`InvalidParameter`: if either the ``key`` and/or ``data`` are not properly formatted.
        """

        Cryptographer.check_data_key_format(message, secret)

        # sk is the H(txid) (32-byte) and nonce is set to 0 (12-byte)
        sk = sha256(unhexlify(secret)).digest()
        nonce = bytearray(12)

        # Encrypt the data
        cipher = ChaCha20Poly1305(sk)
        encrypted_blob = cipher.encrypt(nonce=nonce,
                                        data=unhexlify(message),
                                        associated_data=None)
        encrypted_blob = hexlify(encrypted_blob).decode("utf8")

        return encrypted_blob
Exemple #8
0
def verify_start(config: Config, context: dict, ios_device_public_key: bytes) -> List[dict]:
    """pair_verify M1 and M2"""
    curve25519 = X25519PrivateKey.generate()
    accessory_curve25519_public_key: bytes = curve25519.public_key().public_bytes()
    shared_secret: bytes = curve25519.exchange(X25519PublicKey.from_public_bytes(ios_device_public_key))

    accessory_info: bytes = accessory_curve25519_public_key + config.device_id.encode() + ios_device_public_key
    signing_key = ed25519.SigningKey(config.accessory_ltsk)
    accessory_signature = signing_key.sign(accessory_info)

    sub_tlv = tlv_parser.encode([{
        TlvCode.identifier: config.device_id,
        TlvCode.signature: accessory_signature,
    }])

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_VERIFY, info=INFO_VERIFY, backend=default_backend())
    session_key = hkdf.derive(shared_secret)

    chacha = ChaCha20Poly1305(session_key)
    encrypted_data = chacha.encrypt(NONCE_VERIFY_M2, sub_tlv, None)

    context['session_key'] = session_key
    context['shared_secret'] = shared_secret
    context['accessory_curve25519_public_key'] = accessory_curve25519_public_key
    context['ios_device_curve25519_public_key'] = ios_device_public_key

    return [{
        TlvCode.state: TlvState.m2,
        TlvCode.public_key: accessory_curve25519_public_key,
        TlvCode.encrypted_data: encrypted_data,
    }]
Exemple #9
0
def gen(
    version_id=version_id, client_key=client_key, encryption_secret=encryption_secret,
    app_id=1, version=1):
    # first, generate the encryption key
    salt = hashlib.sha256(uuid.UUID(client_key).bytes).digest()
    key = pbkdf2.PBKDF2(
        encryption_secret,
        salt,
        digestmodule=hashlib.sha256,
        iterations=100000,
    ).read(32)

    # create a nonce
    nonce = secrets.token_bytes(12)

    assert len(b"\x01") == 1
    # create the AAD
    aad = b''.join([
        bytes([app_id]),
        uuid.UUID(version_id).bytes,
    ])

    # encrypt using AEAD
    chacha = ChaCha20Poly1305(key)
    ciphertext = chacha.encrypt(nonce, b"SUCCESS", aad)

    # create the envelope
    envelope = b''.join([
        bytes([version]),
        nonce,
        ciphertext,
    ])

    return envelope
Exemple #10
0
def chacha_poly_encrypt(
    key: bytes, iv: bytes, data: bytes, additional_data: bytes = None
) -> (bytes, bytes):
    chacha = ChaCha20Poly1305(key)
    chacha_output = chacha.encrypt(iv, bytes(data), additional_data)
    # cipher text and 128b authentication tag
    return chacha_output[: len(data)], chacha_output[len(data) :]
Exemple #11
0
 def decrypt(self, key, nonce, ad, ciphertext):
     try:
         return ChaCha20Poly1305(key).decrypt(
             self.__class__._format_nonce(nonce), ciphertext, ad)
     except InvalidTag:
         raise DecryptFailedException(
             reason=DecryptFailedException.REASON_INVALID_TAG)
Exemple #12
0
 def test_decrypt_bad_key(self):
     adapter = adapters.chacha20_poly1305()
     key = b'<key>'.ljust(32, b'\x00')
     nonce = os.urandom(12)
     ciphertext = ChaCha20Poly1305(key).encrypt(nonce, b'<some data>', None)
     with pytest.raises(exceptions.ReplicatError):
         adapter.decrypt(nonce + ciphertext, b'<bad key>'.ljust(32, b'\x00'))
Exemple #13
0
def parser(msg):
    print(msg)
    greeting = msg.startswith("GARAGEMAGIC")
    if not greeting:
        return "BADMAGIC"
    try:
        b64decoded = base64.urlsafe_b64decode(msg[11:])
    except:
        return "BADDECODE"
    nonce = b64decoded[0:12]
    aad = b64decoded[12:24]
    ciphertext = b64decoded[24:]

    chacha = ChaCha20Poly1305(read_private_key())
    try:
        decmsg = chacha.decrypt(nonce, ciphertext, aad)
    except:
        return "BADCRYPTO"

    if not decmsg.startswith(b"OPEN"):
        return "BADCMD"

    cmdtime = int(aad)
    print(cmdtime)
    if abs(cmdtime - time.time()) > 5:
        return "BADTIME"

    #need to take an action here
    toggle_garage_door()
    return "OK"
 def connection_made(self, transport):
     plaintext = self.message.encode()
     nonce = os.urandom(12)
     ciphertext = ChaCha20Poly1305(self._client_write_key).encrypt(
         nonce, plaintext, b"")
     transport.write(nonce + ciphertext)
     print("Encrypted data sent: {!r}".format(self.message))
Exemple #15
0
def body_decrypt(checksum, session_key, nonce, infile,
                 process_output=None,
                 nonce_count=1):
    '''Decrypting the data section and verifying its sha256 checksum'''
    LOG.info("Decrypting content")
    md = hashlib.sha256()
    cipher = ChaCha20Poly1305(session_key)
    nonce_gen = nonce_generator(nonce, counter=nonce_count)
    chunk_size = BLOCK_SIZE + 16

    do_process = callable(process_output)
    chunk = infile.read(chunk_size)
    while chunk:
        decrypted_data = cipher.decrypt(next(nonce_gen), chunk, None) # No aad
        md.update(decrypted_data)
        if do_process:
            process_output(decrypted_data)
        chunk = infile.read(chunk_size)

    # Rewind to add the checksum
    if not compare_digest(checksum, md.digest()):
        LOG.debug(f'Computed MDC: {md.hexdigest().upper()}')
        LOG.debug(f'Original MDC: {checksum.hex().upper()}')
        raise ValueError('Invalid checksum')

    LOG.info('Decryption Successful')
Exemple #16
0
    def decrypt_password(self, password):
        """
        Encrypt password and hash with SHA265
        :param password: password
        return encryted password
        """ 

        hashhex = password[-64:]
        enc = password[0:-64]

        try:
            dehex = bytes.fromhex(enc)
            msg_nonce = dehex[:12]
            ciphertext = dehex[12:]
            cipher = ChaCha20Poly1305(secret)
            password = cipher.decrypt(msg_nonce, ciphertext, None)
        except InvalidTag:
            print_error("Wrong encryption key")
            sys.exit(1)

        hash_object = hashes.Hash(hashes.SHA256(), backend=default_backend())
        hash_object.update(password)
        dhash = hash_object.finalize()
        hashhex_check = dhash.hex()

        if hashhex == hashhex_check:
            return password.decode('utf-8')
        else:
            print_error("Password SHA265 value after decrypt is wrong")
            return None
Exemple #17
0
    def _change_key(self, new_key: bytes) -> NoReturn:
        """Change the encryption _key of the socket and create a new encoder.

        :param new_key: The new _key to use for encryption.
        """
        self._key = new_key
        self.encoder = ChaCha20Poly1305(self._key)
Exemple #18
0
    def _pairing_three(self, tlv_objects):
        """Expand the SRP session key to obtain a new key. Use it to verify and decrypt
            the recieved data. Continue to step four.

        @param tlv_objects: The TLV data received from the client.
        @type tlv_object: dict
        """
        logger.debug("Pairing [3/5]")
        encrypted_data = tlv_objects[HAP_TLV_TAGS.ENCRYPTED_DATA]

        session_key = self.accessory_handler.srp_verifier.get_session_key()
        hkdf_enc_key = hap_hkdf(long_to_bytes(session_key),
                                self.PAIRING_3_SALT, self.PAIRING_3_INFO)

        cipher = ChaCha20Poly1305(hkdf_enc_key)
        decrypted_data = cipher.decrypt(self.PAIRING_3_NONCE,
                                        bytes(encrypted_data), b"")
        assert decrypted_data is not None

        dec_tlv_objects = tlv.decode(bytes(decrypted_data))
        client_username = dec_tlv_objects[HAP_TLV_TAGS.USERNAME]
        client_ltpk = dec_tlv_objects[HAP_TLV_TAGS.PUBLIC_KEY]
        client_proof = dec_tlv_objects[HAP_TLV_TAGS.PROOF]

        self._pairing_four(client_username, client_ltpk, client_proof,
                           hkdf_enc_key)
Exemple #19
0
def cryptography_chacha20poly1305(keysize=32, data_size=1024):
    plaintext = get_random_bytes(data_size * 1024)
    aad = get_random_bytes(data_size * 1024)
    key = ChaCha20Poly1305.generate_key()
    chacha = ChaCha20Poly1305(key)
    nonce = get_random_bytes(12)
    _ = chacha.encrypt(nonce, plaintext, aad)
Exemple #20
0
    def encrypt_blob(self, blob: bytes) -> bytes:
        ''' Encrypts `blob` with ChaCha20Poly1305.

            Returns a bytes value (the "message") in the following form:

                {base64'd nonce}${base64'd salt}${base64'd blob}

            Expects `self.key` to be a 32-byte value.
        '''

        if not self.key:
            raise ValueError('Key must be set')

        if len(self.key) != 32:
            raise ValueError('Key must be 32 bytes in length')

        nonce = os.urandom(12)
        algo = ChaCha20Poly1305(self.key)

        enc_blob = algo.encrypt(nonce, blob, None)

        return b'$'.join([
            base64.b64encode(nonce),
            base64.b64encode(self.salt),
            base64.b64encode(enc_blob),
        ])
Exemple #21
0
    async def decrypt_stream(self, reader: StreamReader) -> StreamReader:
        data_length = await reader.read(ENCRYPTED_DATA_LENGTH)

        if not data_length:
            raise SecurityError('Connection closed')

        data_length_int = int.from_bytes(data_length,
                                         byteorder='little') + AUTH_TAG_LENGTH

        encrypted_data = await reader.read(data_length_int)

        chacha = ChaCha20Poly1305(self.context['decrypt_key'])

        nonce = b'\x00\x00\x00\x00' + self.encrypted_request_count.to_bytes(
            8, byteorder='little')
        try:
            decrypted_data = chacha.decrypt(nonce, encrypted_data, data_length)
        except InvalidTag:
            decrypted_data = None

        if not decrypted_data:
            raise SecurityError('Unable to decrypt encrypted data')

        self.encrypted_request_count += 1

        decrypted_reader = StreamReader()
        decrypted_reader.feed_data(decrypted_data)
        return decrypted_reader
def insertMessage(img, msg, aad):

    alteredImg = img.copy()

    #Generate psuedo random order of pixels to modify based on length of msg
    order = random.sample(range(0, img.width * img.height), len(msg) * 2)

    pixels = list(img.getdata())  #Flatten RGBA arrays into a list

    binaryMsg = convertStringToBinary(msg)

    for i in range(0, len(order)):
        for j in range(0, 4):

            pixels[order[i]] = changeLSB(pixels[order[i]],
                                         binaryMsg[(i * 4):((i * 4) + 4)])

    alteredImg.putdata(pixels)  #Place modified pixels into another image
    print(img)
    pyplot.figure(1)

    pyplot.imshow(np.concatenate((img, alteredImg), axis=1))
    pyplot.show()

    orderString = " ".join(map(
        str, order))  #Concatenate pixel coordinates into one whole string
    byteString = bytes(orderString, "ascii")  #Must be byte array to encrpt

    key = ChaCha20Poly1305.generate_key()
    print("Here is your private key: ", key)
    chacha = ChaCha20Poly1305(key)
    nonce = os.urandom(12)
    ct = chacha.encrypt(nonce, byteString, bytes(aad, "ascii"))

    print("Using key to decrypt image associated with", aad, "\n")

    decryptString = chacha.decrypt(nonce, ct, bytes(aad, "ascii"))

    decodeString = decryptString.decode("ascii")

    decryptOrder = list(map(int, decodeString.split()))

    decryptMsg = ""

    alteredPixels = list(alteredImg.getdata())

    for i in range(0, len(decryptOrder)):
        for j in range(0, 4):
            decryptMsg = decryptMsg + findLSB(
                alteredPixels[decryptOrder[i]][j])

        if (i % 2 == 1):
            decryptMsg = decryptMsg + " "

    decryptMsg = decryptMsg.split()

    decryptMsg = "".join(list(map(lambda x: chr(int(x, 2)), decryptMsg)))

    print("Here is the decrypted message: ", decryptMsg)
Exemple #23
0
 def test_encrypt(self):
     adapter = adapters.chacha20_poly1305()
     key = b'<key>'.ljust(32, b'\x00')
     return_value = adapter.encrypt(b'<some data>', key)
     ciphertext = ChaCha20Poly1305(key).encrypt(
         return_value[:12], b'<some data>', None
     )
     assert return_value[12:] == ciphertext
Exemple #24
0
    def test_nonce_not_12_bytes(self, backend):
        key = ChaCha20Poly1305.generate_key()
        chacha = ChaCha20Poly1305(key)
        with pytest.raises(ValueError):
            chacha.encrypt(b"00", b"hello", b"")

        with pytest.raises(ValueError):
            chacha.decrypt(b"00", b"hello", b"")
Exemple #25
0
def chacha_poly_decrypt(key: bytes,
                        app_key: int,
                        iv: bytes,
                        data: bytes,
                        additional_data: bytes = None) -> bytes:
    chacha = ChaCha20Poly1305(key)
    chacha_output = chacha.decrypt(bytes(iv), bytes(data), additional_data)
    return chacha_output
Exemple #26
0
    def _pair_verify_two(self, tlv_objects):
        """Verify the client proof and upgrade to encrypted transport.

        @param tlv_objects: The TLV data received from the client.
        @type tlv_object: dict
        """
        logger.debug("Pair verify [2/2]")
        encrypted_data = tlv_objects[HAP_TLV_TAGS.ENCRYPTED_DATA]
        cipher = ChaCha20Poly1305(self.enc_context["pre_session_key"])
        decrypted_data = cipher.decrypt(self.PVERIFY_2_NONCE,
                                        bytes(encrypted_data), b"")
        assert decrypted_data is not None  # TODO:

        dec_tlv_objects = tlv.decode(bytes(decrypted_data))
        client_username = dec_tlv_objects[HAP_TLV_TAGS.USERNAME]
        material = (self.enc_context["client_public"] + client_username +
                    self.enc_context["public_key"].serialize())

        client_uuid = uuid.UUID(str(client_username, "ascii"))
        perm_client_public = self.state.paired_clients.get(client_uuid)
        if perm_client_public is None:
            logger.debug(
                "Client %s attempted pair verify without being paired first.",
                client_uuid,
            )
            self.send_response(200)
            self.send_header("Content-Type", self.PAIRING_RESPONSE_TYPE)
            data = tlv.encode(HAP_TLV_TAGS.ERROR_CODE,
                              HAP_OPERATION_CODE.INVALID_REQUEST)
            self.end_response(data)
            return

        verifying_key = ed25519.VerifyingKey(perm_client_public)
        try:
            verifying_key.verify(dec_tlv_objects[HAP_TLV_TAGS.PROOF], material)
        except ed25519.BadSignatureError:
            logger.error("Bad signature, abort.")
            self.send_response(200)
            self.send_header("Content-Type", self.PAIRING_RESPONSE_TYPE)
            data = tlv.encode(HAP_TLV_TAGS.ERROR_CODE,
                              HAP_OPERATION_CODE.INVALID_REQUEST)
            self.end_response(data)
            return

        logger.debug(
            "Pair verify with client '%s' completed. Switching to "
            "encrypted transport.",
            self.client_address,
        )

        data = tlv.encode(HAP_TLV_TAGS.SEQUENCE_NUM, b"\x04")
        self.send_response(200)
        self.send_header("Content-Type", self.PAIRING_RESPONSE_TYPE)
        self.end_response(data)

        self.response.shared_key = self.enc_context["shared_key"]
        self.is_encrypted = True
        del self.enc_context
Exemple #27
0
def send(conf, receive_name, filename):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_host, server_port = get_address(conf, receive_name)
    print('connecting to {}:{}'.format(server_host, server_port))
    sock.connect((server_host, server_port))
    # Receive Public Key
    pk = b''
    print("receiving public key...")
    while True:
        resp = sock.recv(4096)
        pk += resp
        if len(resp) < 4096:
            break
    pk = pk.decode()
    print("public key received is {}".format(pk))
    if receive_name not in conf["publicKeys"]:
        print(
            "This peer has not a Public Key registered. Want to register this PK? (Y/n)"
        )
        if input() == "n":
            print("Could not verify PK, ending connection...")
            sock.close()
            exit(1)
        else:
            print("Accepting PK received as {}'s Public Key".format(
                receive_name))
            add_public_key(conf, receive_name, pk)
    else:
        if conf["publicKeys"][receive_name] != pk:
            print("public key mismatch. MITM!")
            exit(1)
        else:
            print("PK received matches with registered PK for {}".format(
                receive_name))
            # Key is ok, send symmetric encryption key and then the file
    print(
        "Generating shared key for ChaCha20Poly1305 authenticated encryption..."
    )
    key = ChaCha20Poly1305.generate_key()  # 32 bytes
    encrypted_shared_key = get_encrypted_shared_key(key, pk)
    chacha20 = ChaCha20Poly1305(key)
    print("Generating encrypted shared key to receiver...")
    sock.sendall(encrypted_shared_key)
    i = 0
    filesize = os.path.getsize(filename)
    print("sending total filesize ({} bytes) in 8 bytes and in plain text".
          format(filesize))
    sock.sendall(filesize.to_bytes(8, byteorder="big"))
    print("Sending encrypted file to receiver")
    with open(filename, 'rb') as f:
        for chunk in iter(partial(f.read, CHUNK_SIZE), b''):
            encrypted = chacha20.encrypt(i.to_bytes(12, byteorder="big"),
                                         chunk, None)
            print("sending package of size {}...".format(len(encrypted)))
            i += 1
            sock.sendall(encrypted)
    sock.close()
    print("done!")
Exemple #28
0
    def _encrypt(self, content, password):
        salt = os.urandom(16)
        kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, backend=default_backend())
        key = kdf.derive(password)
        cipher = ChaCha20Poly1305(key)

        nonce = os.urandom(12)
        ciphertext = cipher.encrypt(nonce, content, None)
        return salt + nonce + ciphertext
Exemple #29
0
    def test_params_not_bytes_encrypt(self, nonce, data, associated_data,
                                      backend):
        key = ChaCha20Poly1305.generate_key()
        chacha = ChaCha20Poly1305(key)
        with pytest.raises(TypeError):
            chacha.encrypt(nonce, data, associated_data)

        with pytest.raises(TypeError):
            chacha.decrypt(nonce, data, associated_data)
Exemple #30
0
def decrypt(key, encrypted):
    """Decrypt age-encrypted data."""
    cipher = ChaCha20Poly1305(key)
    try:
        return cipher.decrypt(nonce=(b"\x00" * 12),
                              data=encrypted,
                              associated_data=None)
    except InvalidTag:
        return None