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)
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
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()
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
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
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, }]
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
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) :]
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)
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'))
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))
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')
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
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)
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)
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)
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), ])
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)
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
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"")
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
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
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!")
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
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)
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