[PYTHON-CRYPTO] things missing from PEP 272
phr-pycrypt at nightsong.com
Mon Mar 18 07:00:22 CET 2002
The standard NIST cipher modes are defined in this document
The modes it gives are CBC, ECB, CFB, OFB, and CTR, the last two of which
are missing from PEP 272. Some further justification for CTR is given
I'd really like CTR to ship with Python because, well, I'm using it, and
it's the only thing keeping my app from being pure Python :-)
I agree that CTR mode should be included. I think OFB and CFB modes
can be dropped. I think PGP mode should be be dropped unless someone
specifically wants to write a PGP-compatible application. Certainly,
implementations of the API should not be REQUIRED to support all these
The API for OFB is obvious, but the one for CTR is considerably less so.
My suggestion is to have the IV be the first block to be encrypted, and
have the big/little endian issue be addressed by having CTR mean big
endian and CLE mean little endian.
The IV for counter mode should be an int or long giving the counter
value. CTR/CLE for endianness is ok, or just choose one endianness
and stick to it. Are there any applications/standards with specific
Actually, I just read the PEP and it looks to me like it needs several
1. It says nothing about padding methods. CBC mode should probably
pad per RFC 1423 a/k/a PKCS #5. I don't know about CFB mode.
Requiring that the plaintext size be a multiple of the block size
means there has to be another API layer to deal with padding. That
seems clumsy to me, but if it's what's intended, the PEP should also
specify that layer. I'd rather permit arbitrary lengths for
plaintext and specify a padding algorithm. It's best to specify how
to do what users actually want, instead of leaving them on their own
to code up some unspecified intermediate layer. I.e. if you're
going to specify a function taking a string plaintext arg and
returning a string ciphertext, it should handle arbitrary lengths.
2. The treatment of stream ciphers is bogus. The idea of ECB mode for
a stream cipher makes no sense at all. Stream ciphers should use CTR
or CFB mode. They should be treated separately from block ciphers
rather than kludged in by specifying a block size of 1.
3. The specifications of block_size and key_size are vague: is
"size" measured in bits, or in bytes? The key and data args to
the encryption function are byte strings, so block_size should
probably be bytes (too bad for 1-bit CFB mode or 1-bit stream
ciphers). Usually though we think of "56-bit DES" or "128-bit AES",
so it's slightly surprising (but ok) to have key_size be bytes.
4. The key_size variable must be either an integer (a specific number
of bits), or None (meaning any length at all is valid). This doesn't
handle AES very well--AES accepts 128, 192, or 256 bits, but not other
values. RC4 accepts any key length that's a multiple of 8 bits, but
won't accept (say) 23 bits. Maybe this variable should just be
eliminated, and let the module throw an error if you try to set a
key length it doesn't like.
5. I think it should be ok to pass an initial IV of None or 0,
equivalent to "\0"*(module.block_size) where block_size is in bytes.
Usually you use IV=0 to compute a CBC MAC, for example.
6. The PEP should specify what exceptions the modules can raise and when.
7. There should be a 'mac' operation added, similar to encrypt and
decrypt. MAC runs the cipher and updates the IV and returns the
final IV instead of encrypted or decrypted text. There should also
be a 'verify' operation which tests whether a string has a given MAC
and returns 1 or 0.
8. The encrypt, decrypt, mac, and verify operations should all be
allowed to raise NotImplementedError if the cipher doesn't support
that mode. It's perfectly ok for a cipher to support encryption
but not decryption, or a cipher to not support PGP chaining mode, etc.
More information about the python-crypto