def test__messages_from_up_to_a_minute_in_the_future_accepted(self): self.write_secret() testdata = factory.make_bytes() now = time.time() self.patch(time, "time").side_effect = [now + 60, now] token = fernet_encrypt_psk(testdata) fernet_decrypt_psk(token, ttl=1)
def test__messages_from_future_exceeding_clock_skew_limit_rejected(self): self.write_secret() testdata = factory.make_bytes() now = time.time() self.patch(time, "time").side_effect = [now + 61, now] token = fernet_encrypt_psk(testdata) with ExpectedException(InvalidToken): fernet_decrypt_psk(token, ttl=1)
def test__can_encrypt_and_decrypt_with_raw_bytes(self): self.write_secret() testdata = factory.make_bytes() token = fernet_encrypt_psk(testdata, raw=True) self.assertThat(token, IsInstance(bytes)) decrypted = fernet_decrypt_psk(token, raw=True) self.assertThat(decrypted, Equals(testdata))
def test__assures_data_integrity(self): self.write_secret() testdata = factory.make_bytes(size=10) token = fernet_encrypt_psk(testdata) bad_token = bytearray(token) # Flip a bit in the token, so we can ensure it won't decrypt if it # has been corrupted. Subtract 4 to avoid the end of the token; that # portion is just padding, and isn't covered by the HMAC. byte_to_flip = randint(0, len(bad_token) - 4) bit_to_flip = 1 << randint(0, 7) bad_token[byte_to_flip] ^= bit_to_flip bad_token = bytes(bad_token) test_description = ("token=%s; token[%d] ^= 0x%02x" % ( token.decode("utf-8"), byte_to_flip, bit_to_flip)) with ExpectedException(InvalidToken, msg=test_description): fernet_decrypt_psk(bad_token)
def read_beacon_payload(beacon_bytes): """Returns a BeaconPayload namedtuple representing the given beacon bytes. Decrypts the inner beacon data if necessary. :param beacon_bytes: beacon payload (bytes). :return: BeaconPayload namedtuple """ if len(beacon_bytes) < BEACON_HEADER_LENGTH_V1: raise InvalidBeaconingPacket( "Beaconing packet must be at least %d bytes." % BEACON_HEADER_LENGTH_V1 ) header = beacon_bytes[:BEACON_HEADER_LENGTH_V1] version, beacon_type_code, expected_payload_length = struct.unpack( BEACON_HEADER_FORMAT_V1, header ) actual_payload_length = len(beacon_bytes) - BEACON_HEADER_LENGTH_V1 if len(beacon_bytes) - BEACON_HEADER_LENGTH_V1 < expected_payload_length: raise InvalidBeaconingPacket( "Invalid payload length: expected %d bytes, got %d bytes." % (expected_payload_length, actual_payload_length) ) payload_start = BEACON_HEADER_LENGTH_V1 payload_end = BEACON_HEADER_LENGTH_V1 + expected_payload_length payload_bytes = beacon_bytes[payload_start:payload_end] payload = None if version == 1: if len(payload_bytes) == 0: # No encrypted inner payload; nothing to do. pass else: try: decrypted_data = fernet_decrypt_psk( payload_bytes, ttl=60, raw=True ) except InvalidToken: raise InvalidBeaconingPacket( "Failed to decrypt inner payload: check MAAS secret key." ) try: decompressed_data = decompress(decrypted_data) except OSError: raise InvalidBeaconingPacket( "Failed to decompress inner payload: %r" % decrypted_data ) try: # Replace the data in the dictionary with its decrypted form. payload = BSON.decode(decompressed_data) except BSONError: raise InvalidBeaconingPacket( "Inner beacon payload is not BSON: %r" % decompressed_data ) else: raise InvalidBeaconingPacket("Unknown beacon version: %d" % version) beacon_type_code = payload["type"] if payload else beacon_type_code return BeaconPayload( beacon_bytes, version, BEACON_TYPE_VALUES[beacon_type_code], payload )
def test__can_encrypt_and_decrypt_string(self): self.write_secret() testdata = factory.make_string() token = fernet_encrypt_psk(testdata) # Round-trip this to a string, since Fernet tokens are used inside # strings (such as JSON objects) typically. token = token.decode("ascii") decrypted = fernet_decrypt_psk(token) decrypted = decrypted.decode("ascii") self.assertThat(decrypted, Equals(testdata))
def test__derives_identical_key_on_decrypt(self): self.write_secret() self.assertIsNone(security._fernet_psk) testdata = factory.make_bytes() token = fernet_encrypt_psk(testdata) first_key = security._fernet_psk # Make it seem like we're decrypting something without ever encrypting # anything first. security._fernet_psk = None decrypted = fernet_decrypt_psk(token) second_key = security._fernet_psk self.assertEqual(first_key, second_key) self.assertEqual(testdata, decrypted)
def test__raises_when_no_secret_exists(self): testdata = factory.make_bytes() with ExpectedException(MissingSharedSecret): fernet_encrypt_psk(testdata) with ExpectedException(MissingSharedSecret): fernet_decrypt_psk(b"")
def test__can_encrypt_and_decrypt_bytes(self): self.write_secret() testdata = factory.make_bytes() token = fernet_encrypt_psk(testdata) decrypted = fernet_decrypt_psk(token) self.assertThat(decrypted, Equals(testdata))