245 lines
8.4 KiB
ReStructuredText
245 lines
8.4 KiB
ReStructuredText
PEP: 272
|
|
Title: API for Block Encryption Algorithms v1.0
|
|
Version: $Revision$
|
|
Last-Modified: $Date$
|
|
Author: A.M. Kuchling <amk@amk.ca>
|
|
Status: Final
|
|
Type: Informational
|
|
Content-Type: text/x-rst
|
|
Created: 18-Sep-2001
|
|
Post-History: 17-Apr-2002, 29-May-2002
|
|
|
|
|
|
Abstract
|
|
========
|
|
|
|
This document specifies a standard API for secret-key block
|
|
encryption algorithms such as DES or Rijndael, making it easier to
|
|
switch between different algorithms and implementations.
|
|
|
|
|
|
Introduction
|
|
============
|
|
|
|
Encryption algorithms transform their input data (called
|
|
plaintext) in some way that is dependent on a variable key,
|
|
producing ciphertext. The transformation can easily be reversed
|
|
if and only if one knows the key. The key is a sequence of bits
|
|
chosen from some very large space of possible keys. There are two
|
|
classes of encryption algorithms: block ciphers and stream ciphers.
|
|
|
|
Block ciphers encrypt multibyte inputs of a fixed size (frequently
|
|
8 or 16 bytes long), and can be operated in various feedback
|
|
modes. The feedback modes supported in this specification are:
|
|
|
|
====== ======== =====================
|
|
Number Constant Description
|
|
====== ======== =====================
|
|
1 MODE_ECB Electronic Code Book
|
|
2 MODE_CBC Cipher Block Chaining
|
|
3 MODE_CFB Cipher Feedback
|
|
5 MODE_OFB Output Feedback
|
|
6 MODE_CTR Counter
|
|
====== ======== =====================
|
|
|
|
These modes are to be implemented as described in NIST publication
|
|
SP 800-38A [1]_. Descriptions of the first three feedback modes can
|
|
also be found in Bruce Schneier's book *Applied Cryptography* [2]_.
|
|
|
|
(The numeric value 4 is reserved for MODE_PGP, a variant of CFB
|
|
described in :rfc:`2440`: "OpenPGP Message Format". This mode
|
|
isn't considered important enough to make it worth requiring it
|
|
for all block encryption ciphers, though supporting it is a nice
|
|
extra feature.)
|
|
|
|
In a strict formal sense, stream ciphers encrypt data bit-by-bit;
|
|
practically, stream ciphers work on a character-by-character
|
|
basis. This PEP only aims at specifying an interface for block
|
|
ciphers, though stream ciphers can support the interface described
|
|
here by fixing 'block_size' to 1. Feedback modes also don't make
|
|
sense for stream ciphers, so the only reasonable feedback mode
|
|
would be ECB mode.
|
|
|
|
|
|
Specification
|
|
=============
|
|
|
|
Encryption modules can add additional functions, methods, and
|
|
attributes beyond those described in this PEP, but all of the
|
|
features described in this PEP must be present for a module to
|
|
claim compliance with it.
|
|
|
|
Secret-key encryption modules should define one function::
|
|
|
|
new(key, mode, [IV], **kwargs)
|
|
|
|
Returns a ciphering object, using the secret key contained in the
|
|
string 'key', and using the feedback mode 'mode', which must be
|
|
one of the constants from the table above.
|
|
|
|
If 'mode' is MODE_CBC or MODE_CFB, 'IV' must be provided and must
|
|
be a string of the same length as the block size. Not providing a
|
|
value of 'IV' will result in a ``ValueError`` exception being raised.
|
|
|
|
Depending on the algorithm, a module may support additional
|
|
keyword arguments to this function. Some keyword arguments are
|
|
specified by this PEP, and modules are free to add additional
|
|
keyword arguments. If a value isn't provided for a given keyword,
|
|
a secure default value should be used. For example, if an
|
|
algorithm has a selectable number of rounds between 1 and 16, and
|
|
1-round encryption is insecure and 8-round encryption is believed
|
|
secure, the default value for 'rounds' should be 8 or more.
|
|
(Module implementors can choose a very slow but secure value, too,
|
|
such as 16 in this example. This decision is left up to the
|
|
implementor.)
|
|
|
|
The following table lists keyword arguments defined by this PEP:
|
|
|
|
============ ============================================
|
|
Keyword Meaning
|
|
============ ============================================
|
|
counter Callable object that returns counter blocks
|
|
(see below; CTR mode only)
|
|
|
|
rounds Number of rounds of encryption to use
|
|
|
|
segment_size Size of data and ciphertext segments,
|
|
measured in bits (see below; CFB mode only)
|
|
============ ============================================
|
|
|
|
The Counter feedback mode requires a sequence of input blocks,
|
|
called counters, that are used to produce the output. When 'mode'
|
|
is MODE_CTR, the 'counter' keyword argument must be provided, and
|
|
its value must be a callable object, such as a function or method.
|
|
Successive calls to this callable object must return a sequence of
|
|
strings that are of the length 'block_size' and that never
|
|
repeats. (Appendix B of the NIST publication gives a way to
|
|
generate such a sequence, but that's beyond the scope of this
|
|
PEP.)
|
|
|
|
The CFB mode operates on segments of the plaintext and ciphertext
|
|
that are 'segment_size' bits long. Therefore, when using this
|
|
mode, the input and output strings must be a multiple of
|
|
'segment_size' bits in length. 'segment_size' must be an integer
|
|
between 1 and block_size\*8, inclusive. (The factor of 8 comes
|
|
from 'block_size' being measured in bytes and not in bits). The
|
|
default value for this parameter should be block_size\*8.
|
|
Implementors are allowed to constrain 'segment_size' to be a
|
|
multiple of 8 for simplicity, but they're encouraged to support
|
|
arbitrary values for generality.
|
|
|
|
Secret-key encryption modules should define two variables:
|
|
|
|
- block_size
|
|
|
|
An integer value; the size of the blocks encrypted by this
|
|
module, measured in bytes. For all feedback modes, the length
|
|
of strings passed to the encrypt() and decrypt() must be a
|
|
multiple of the block size.
|
|
|
|
- key_size
|
|
|
|
An integer value; the size of the keys required by this
|
|
module, measured in bytes. If key_size is None, then the
|
|
algorithm accepts variable-length keys. This may mean the
|
|
module accepts keys of any random length, or that there are a
|
|
few different possible lengths, e.g. 16, 24, or 32 bytes. You
|
|
cannot pass a key of length 0 (that is, the null string '') as
|
|
a variable-length key.
|
|
|
|
|
|
Cipher objects should have two attributes:
|
|
|
|
- block_size
|
|
|
|
An integer value equal to the size of the blocks encrypted by
|
|
this object. For algorithms with a variable block size, this
|
|
value is equal to the block size selected for this object.
|
|
|
|
- IV
|
|
|
|
Contains the initial value which will be used to start a
|
|
cipher feedback mode; it will always be a string exactly one
|
|
block in length. After encrypting or decrypting a string,
|
|
this value is updated to reflect the modified feedback text.
|
|
It is read-only, and cannot be assigned a new value.
|
|
|
|
|
|
Cipher objects require the following methods:
|
|
|
|
- decrypt(string)
|
|
|
|
Decrypts 'string', using the key-dependent data in the object
|
|
and with the appropriate feedback mode. The string's length
|
|
must be an exact multiple of the algorithm's block size or, in
|
|
CFB mode, of the segment size. Returns a string containing
|
|
the plaintext.
|
|
|
|
- encrypt(string)
|
|
|
|
Encrypts a non-empty string, using the key-dependent data in
|
|
the object, and with the appropriate feedback mode. The
|
|
string's length must be an exact multiple of the algorithm's
|
|
block size or, in CFB mode, of the segment size. Returns a
|
|
string containing the ciphertext.
|
|
|
|
Here's an example, using a module named 'DES'::
|
|
|
|
>>> import DES
|
|
>>> obj = DES.new('abcdefgh', DES.MODE_ECB)
|
|
>>> plaintext = "Guido van Rossum is a space alien."
|
|
>>> len(plaintext)
|
|
34
|
|
>>> obj.encrypt(plaintext)
|
|
Traceback (innermost last):
|
|
File "<stdin>", line 1, in ?
|
|
ValueError: Strings for DES must be a multiple of 8 in length
|
|
>>> ciphertext = obj.encrypt(plain+'XXXXXX') # Add padding
|
|
>>> ciphertext
|
|
'\021,\343Nq\214DY\337T\342pA\372\255\311s\210\363,\300j\330\250\312\347\342I\3215w\03561\303dgb/\006'
|
|
>>> obj.decrypt(ciphertext)
|
|
'Guido van Rossum is a space alien.XXXXXX'
|
|
|
|
|
|
References
|
|
==========
|
|
|
|
.. [1] NIST publication SP 800-38A, "Recommendation for Block Cipher
|
|
Modes of Operation" (http://csrc.nist.gov/encryption/modes/)
|
|
|
|
.. [2] Applied Cryptography
|
|
|
|
|
|
Changes
|
|
=======
|
|
|
|
2002-04: Removed references to stream ciphers; retitled PEP;
|
|
prefixed feedback mode constants with ``MODE_``; removed PGP feedback
|
|
mode; added CTR and OFB feedback modes; clarified where numbers
|
|
are measured in bytes and where in bits.
|
|
|
|
2002-09: Clarified the discussion of key length by using
|
|
"variable-length keys" instead of "arbitrary-length".
|
|
|
|
|
|
Acknowledgements
|
|
================
|
|
|
|
Thanks to the readers of the python-crypto list for their comments on
|
|
this PEP.
|
|
|
|
|
|
Copyright
|
|
=========
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
..
|
|
Local Variables:
|
|
mode: indented-text
|
|
indent-tabs-mode: nil
|
|
End:
|
|
|