Miscreant (Python)
Miscreant.py is a Python implementation of the Miscreant advanced symmetric encryption library, providing AES-SIV (RFC 5297), AES-PMAC-SIV, and STREAM constructions. These algorithms offer misuse-resistant authenticated encryption, particularly AES-SIV, which prevents catastrophic failures from nonce reuse. The last stable version is 0.3.0, released in December 2017, and the project is effectively unmaintained.
Warnings
- breaking The Miscreant Python repository is marked as 'Public archive' on GitHub, indicating that it is no longer actively maintained. No further development, bug fixes, or security patches are expected.
- gotcha Some portions of the Miscreant implementation (specifically `s2v` and `dbl` functions) are in pure Python and are NOT constant time. This means they may be vulnerable to timing attacks that could reveal sensitive information, potentially leading to plaintext recovery.
- gotcha The AES-SIV construction requires a key that is twice the size of a standard AES key (e.g., 32 bytes for AES-128 SIV, or 64 bytes for AES-256 SIV). Passing an incorrectly sized key will result in an error or insecure operation.
- gotcha The PyPI project for miscreant (version 0.3.0) is still classified with a 'Development Status :: 2 - Pre-Alpha'. This indicates that it was never considered stable or production-ready by its maintainers, even at its last release.
Install
-
pip install miscreant
Imports
- SIV
from miscreant.aes.siv import SIV
Quickstart
import os
from miscreant.aes.siv import SIV
# AES-SIV requires a key twice the size of a standard AES key (e.g., 32 or 64 bytes)
# For a 128-bit AES-SIV key, generate 32 bytes (2 * 16 bytes)
key = os.urandom(32)
siv = SIV(key)
plaintext = b"This is my secret message!"
# Associated data (AD) is authenticated but not encrypted
associated_data = [b"header1", b"header2"]
# Encrypt (seal) the message
ciphertext = siv.seal(plaintext, ad=associated_data)
print(f"Ciphertext: {ciphertext.hex()}")
# Decrypt (open) the message
try:
decrypted_plaintext = siv.open(ciphertext, ad=associated_data)
print(f"Decrypted: {decrypted_plaintext.decode()}")
except Exception as e:
print(f"Decryption failed: {e}")