예제 #1
0
 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)
예제 #2
0
 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)
예제 #3
0
 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))
예제 #4
0
 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)
예제 #5
0
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
    )
예제 #6
0
 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))
예제 #7
0
 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)
예제 #8
0
 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"")
예제 #9
0
 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))