skip to navigation
skip to content

Python Wiki

Python Insider Blog

Python 2 or 3?

Help Fund Python

[Python resources in languages other than English]

Non-English Resources

Add an event to this calendar.

Times are shown in UTC/GMT.

Add an event to this calendar.

PEP: 272
Title: API for Block Encryption Algorithms v1.0
Version: 5e81fa0e368a
Last-Modified:  2006-03-23 20:13:19 +0000 (Thu, 23 Mar 2006)
Author: A.M. Kuchling <amk at amk.ca>
Status: Final
Type: Informational
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" [3]. 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

    [3] RFC2440: "OpenPGP Message Format" (http://rfc2440.x42.com,
    http://www.faqs.org/rfcs/rfc2440.html)


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.