Implementation of several cryptographic primitives. I created this library to to test specific attacks on existing cryptograpy.
Performance is not a priority and I make no effort from prevented anyone from using the wrong schemes. My only goals here are to make correct implementations which are easy to use.
#!/usr/bin/env python2
from crypturd import encrypt,decrypt
# Input message and key are strings or arbitrary length
message = "Attack at dawn!"
key = "yKj3xBCBatVG1Q0gZ8ss2xbC4"
# Generate ciphertext from message and key
# Default symmetric key cipher is chacha20+poly1305
ciphertext = encrypt(message,key)
# Recover plaintext from ciphertext
plaintext = decrypt(ciphertext,key)
Symmetric key crypto | MAC | Key exchange | Signature | RNG |
---|---|---|---|---|
ChaCha20 | Poly1305 | ECDH (Ed25519) | Manytimessig (custom) | ChaCha20 |
Symmetric key crypto | MAC | Key exchange | Signature |
---|---|---|---|
RC4 (Weak) | CBC-MAC (weak) | RSA | RSA |
AES-128 (ECB/CBC/CTR) | SHA256-HMAC | ECDH (Ed25519) | DSA |
AES-256 (ECB/CBC/CTR) | Poly1305 | Manytimessig (custom) | |
ChaCha20 | statelessig (custom) |
Padding | Random Number generator | Hash |
---|---|---|
Null Padding | RC4 (weak) | MD4 (Weak) |
PKCS7 | MT19937 (weak) | SHA1 (Weak) |
AES-128-CTR | SHA256 | |
ChaCha20 |
This is a single man project, nobody except the author has reviewed this code.
USE AT YOUR OWN RISK
Based on input/output all primitives are implemented correctly. However this does not necessarily exclude the possibility of side-channel attacks.
Some primitives included in this library easily broken, do not use them for anything you care about. The default hash function, random number generator and symmetric key cipher are chosen to be secure. If in doubt, use the defaults (as specified in default.py).
The current AES implementation can leak its internal state due to timing differences in lookup tables between recently and non-recently accessed values.
ChaCha20 is immune to side-channel attack when implemented correctly. On 64-bit machines the ChaCha20 in this library is not vulnerable to side-channel attacks. However on 32-bit cpu python may treat number in the range 2^31 - 2^32 as bignums, allowing for side-channel attacks.
Due to differences in string formatting in python2 and python3, this library only work with python2.
Error messages are hidden by default to prevent leakage of data. To get accurate exception handling add the following line to your code.
crypturd.common.DEBUG = True
For easy use all cipher can be used with arbitrary size user keys that are converted to appropriately sized keys
- Keys that are shorter than expected are padded with null bytes
- Strings of the correct size are use exactly
- hex formated string of the correct size are used exactly
- Otherwise, the input string is hashed using sha256 (and truncated for 128-bit keys)
The following keys are all treated as if they were identical
- "yellow submarine"
- "yellow submarine\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "79656c6c6f77207375626d6172696e6500000000000000000000000000000000"
The generation of nonces in this library relies on os.urandom(). On common Gnu/Linux distribution (Debian/Ubuntu/Red Hat/Gentoo/Arch/SuSe etc) and BSD systems (OpenBSD,FreeBSD) I can confirm that this functionality is implemented correctly.
On other popular systems (Microsoft Windows, Apple Mac OS and other proprietary systems), I cannot assure that nonces are generated securely.
The general structure of all authenticated ciphers is as follows
(IV or nonce) || (Ciphertext) || MAC
For Chacha20 the format is
96-bit nonce (for both ciphertext and MAC) || Ciphertext || Poly1305 MAC (128 bits)
For most modes AES the format is
128-bit IV (for ciphertext) || Ciphertext || SHA256-MAC (256 bits)
AES-128-ECB and AES-256-ECB do not use Initialization vectors or message authentication codes.
Plaintexts in AES-ECB and AES-CBC are padded using PKCS7.