Пример #1
0
def encrypt_string(pt, key=None):
    """Encrypt the plaintext (pt) with the 16-bytes key. Moreover, it
    encrypts it using a random IV, so that encrypting repeatedly the
    same string gives different outputs. This way no analisys can made
    when the same number is used in different contexts. The generated
    string uses the alphabet { 'a', ..., 'z', 'A', ..., 'Z', '0', ...,
    '9', '.', '-', '_' }, so it is safe to use in URLs.

    If key is not specified, it is obtained from the configuration.

    """
    if key is None:
        key = _get_secret_key_unhex()
    # Pad the plaintext to make its length become a multiple of the block size
    # (that is, for AES, 16 bytes), using a byte 0x01 followed by as many bytes
    # 0x00 as needed. If the length of the message is already a multiple of 16
    # bytes, add a new block.
    pt_pad = bytes(pt) + b'\01' + b'\00' * (16 - (len(pt) + 1) % 16)
    # The IV is a random block used to differentiate messages encrypted with
    # the same key. An IV should never be used more than once in the lifetime
    # of the key. In this way encrypting the same plaintext twice will produce
    # different ciphertexts.
    iv = get_random_key()
    # Initialize the AES cipher with the given key and IV.
    aes = AES.new(key, AES.MODE_CBC, iv)
    ct = aes.encrypt(pt_pad)
    # Convert the ciphertext in a URL-safe base64 encoding
    ct_b64 = bin_to_b64(iv + ct)\
        .replace('+', '-').replace('/', '_').replace('=', '.')
    return ct_b64
Пример #2
0
def encrypt_binary(pt, key_hex):
    """Encrypt the plaintext with the 16-bytes key.

    A random salt is added to avoid having the same input being
    encrypted to the same output.

    pt (bytes): the "plaintext" to encode.
    key_hex (str): a 16-bytes key in hex (a string of 32 hex chars).

    return (str): pt encrypted using the key, in a format URL-safe
        (more precisely, base64-encoded with alphabet "a-zA-Z0-9.-_").

    """
    key = hex_to_bin(key_hex)
    # Pad the plaintext to make its length become a multiple of the block size
    # (that is, for AES, 16 bytes), using a byte 0x01 followed by as many bytes
    # 0x00 as needed. If the length of the message is already a multiple of 16
    # bytes, add a new block.
    pt_pad = pt + b'\01' + b'\00' * (16 - (len(pt) + 1) % 16)
    # The IV is a random block used to differentiate messages encrypted with
    # the same key. An IV should never be used more than once in the lifetime
    # of the key. In this way encrypting the same plaintext twice will produce
    # different ciphertexts.
    iv = get_random_key()
    # Initialize the AES cipher with the given key and IV.
    aes = AES.new(key, AES.MODE_CBC, iv)
    ct = aes.encrypt(pt_pad)
    # Convert the ciphertext in a URL-safe base64 encoding
    ct_b64 = bin_to_b64(iv + ct)\
        .replace('+', '-').replace('/', '_').replace('=', '.')
    return ct_b64
Пример #3
0
def encrypt_binary(pt, key_hex):
    """Encrypt the plaintext with the 16-bytes key.

    A random salt is added to avoid having the same input being
    encrypted to the same output.

    pt (bytes): the "plaintext" to encode.
    key_hex (str): a 16-bytes key in hex (a string of 32 hex chars).

    return (str): pt encrypted using the key, in a format URL-safe
        (more precisely, base64-encoded with alphabet "a-zA-Z0-9.-_").

    """
    key = hex_to_bin(key_hex)
    # Pad the plaintext to make its length become a multiple of the block size
    # (that is, for AES, 16 bytes), using a byte 0x01 followed by as many bytes
    # 0x00 as needed. If the length of the message is already a multiple of 16
    # bytes, add a new block.
    pt_pad = pt + b'\01' + b'\00' * (16 - (len(pt) + 1) % 16)
    # The IV is a random block used to differentiate messages encrypted with
    # the same key. An IV should never be used more than once in the lifetime
    # of the key. In this way encrypting the same plaintext twice will produce
    # different ciphertexts.
    iv = get_random_key()
    # Initialize the AES cipher with the given key and IV.
    aes = AES.new(key, AES.MODE_CBC, iv)
    ct = aes.encrypt(pt_pad)
    # Convert the ciphertext in a URL-safe base64 encoding
    ct_b64 = bin_to_b64(iv + ct)\
        .replace('+', '-').replace('/', '_').replace('=', '.')
    return ct_b64
Пример #4
0
 def test_string(self):
     with self.assertRaises(TypeError):
         bin_to_b64("cms")
Пример #5
0
 def test_success(self):
     self.assertEqual(bin_to_b64(b"\x32\x00\xa0"), "MgCg")
     self.assertEqual(bin_to_b64(b"\xFF\xFF\xFF\xFF"), "/////w==")
     self.assertEqual(bin_to_b64(b"\x00" * 3000), "A" * (3000 * 4 // 3))
Пример #6
0
 def test_decrypt_invalid_encrypted(self):
     # "stuff" is not decryptable.
     encrypted = bin_to_b64(b"stuff")
     with self.assertRaises(ValueError):
         decrypt_binary(encrypted, self.key)
Пример #7
0
 def test_decrypt_invalid_encrypted(self):
     # "stuff" is not decryptable.
     encrypted = bin_to_b64(b"stuff")
     with self.assertRaises(ValueError):
         decrypt_binary(encrypted, self.key)