Skip to content

Commit

Permalink
feat(api)!: expose _raw_ CBC wrappers, with manual padding
Browse files Browse the repository at this point in the history
Leave room for a simpler `CBC_*crypt_buffer_inplace` with automatic padding

This is incompatible with the previous rc0, but the fix is a rename:

- CBC_encrypt_buffer_inplace -> CBC_encrypt_buffer_inplace_raw
- CBC_decrypt_buffer_inplace -> CBC_decrypt_buffer_inplace_raw
  • Loading branch information
naufraghi committed Oct 2, 2023
1 parent 150cd1b commit 90f7b61
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ Given the C API works modifying a buffer in-place, the wrapper offers:
encrypting a copy of the buffer,
- `CTR_xcrypt_buffer_inplace(..)` that works on `bytearray`s only, modifying
the buffer in-place.
- `CBC_encrypt_buffer_inplace(..)` that works on `bytearray`s only, modifying
the buffer in-place.
- `CBC_decrypt_buffer_inplace(..)` that works on `bytearray`s only, modifying
the buffer in-place.
- `CBC_encrypt_buffer_inplace_raw(..)` that works on `bytearray`s only, modifying
the buffer in-place (manual padding).
- `CBC_decrypt_buffer_inplace_raw(..)` that works on `bytearray`s only, modifying
the buffer in-place (manual unpadding).

<details><summary>CBC usage Example:</summary>

CBC usage Example:
```
import tinyaes
import binascii
Expand All @@ -42,14 +43,19 @@ print(text) # b'hello'
# padding plaintext to a multiple of block size
text = pad(text)
print(binascii.hexlify(bytearray(text))) # b'68656c6c6f0b0b0b0b0b0b0b0b0b0b0b' hex representation of added text
aes_enc.CBC_encrypt_buffer_inplace(text) # b'5adc04828f9421c34210b05fe5c92bfd' hex representation of encrypted text
aes_enc.CBC_encrypt_buffer_inplace_raw(text) # b'5adc04828f9421c34210b05fe5c92bfd' hex representation of encrypted text
print(binascii.hexlify(bytearray(text)))
aes_dec.CBC_decrypt_buffer_inplace(text)
aes_dec.CBC_decrypt_buffer_inplace_raw(text)
print(unpad(text)) # b'hello' decrypted, original text
```

</details>

## Release notes

- 1.1.0rc1 (Oct 2, 2023)
- Add Python 3.12 final to the matrix
- Expose _raw_ functions for CBC mode, with manual padding and unpadding
- 1.1.0rc0 (13 Feb 2023)
- Drop support for Python 2.7 (CI tests and builds are disabled, code may still work)
- Add support for CBC mode (unstable API, inplace only, manual padding)
Expand Down
10 changes: 5 additions & 5 deletions tests/test_tinyaes.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,21 @@ def test_different_keys_do_not_decode(data, aes_enc, aes_dec2, aes_dec3):
def test_different_keys_do_not_decode_cbc(data, aes_enc_cbc, aes_dec2_cbc):
data = pad(data)
original_data = data[:len(data) // 2] + data[len(data) // 2:] # Force a copy not allowing any sharing
aes_enc_cbc.CBC_encrypt_buffer_inplace(data)
aes_dec2_cbc.CBC_decrypt_buffer_inplace(data)
aes_enc_cbc.CBC_encrypt_buffer_inplace_raw(data)
aes_dec2_cbc.CBC_decrypt_buffer_inplace_raw(data)
assert data != original_data


@given(data=binary(min_size=2, max_size=100))
def test_cbc_decode(data, aes_enc2_cbc, aes_dec_cbc):
data = pad(data)
original_data = data[:len(data) // 2] + data[len(data) // 2:] # Force a copy not allowing any sharing
aes_enc2_cbc.CBC_encrypt_buffer_inplace(data)
aes_dec_cbc.CBC_decrypt_buffer_inplace(data)
aes_enc2_cbc.CBC_encrypt_buffer_inplace_raw(data)
aes_dec_cbc.CBC_decrypt_buffer_inplace_raw(data)
assert data == original_data


def test_bad_block_size_cbc(aes_enc_cbc, aes_dec2_cbc):
data = bytes.fromhex('00112233445566778899AA')
with pytest.raises(ValueError, match=r"Length of plaintext must be multiple of.*"):
aes_enc_cbc.CBC_encrypt_buffer_inplace(data)
aes_enc_cbc.CBC_encrypt_buffer_inplace_raw(data)
4 changes: 2 additions & 2 deletions tinyaes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ cdef class AES:
def CTR_xcrypt_buffer_inplace(self, bytearray data):
tinyaes.AES_CTR_xcrypt_buffer(&self._ctx, data, len(data))

def CBC_encrypt_buffer_inplace(self, data):
def CBC_encrypt_buffer_inplace_raw(self, data):
if len(data) % AES_KEYLEN:
raise ValueError(f"Length of plaintext must be multiple of {AES_KEYLEN} bytes")
tinyaes.AES_CBC_encrypt_buffer(&self._ctx, data, len(data))
def CBC_decrypt_buffer_inplace(self, data):
def CBC_decrypt_buffer_inplace_raw(self, data):
if len(data) % AES_KEYLEN:
raise ValueError(f"Length of plaintext must be multiple of {AES_KEYLEN} bytes")
tinyaes.AES_CBC_decrypt_buffer(&self._ctx, data, len(data))

0 comments on commit 90f7b61

Please sign in to comment.