IV silently changed meaning in PyCrypto 2.6; violates PEP 272

Bug #1176482 reported by Darsey Litzenberger
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Python-Crypto
Confirmed
Undecided
Unassigned

Bug Description

The meaning of the 'IV' attribute on cipher objects silently changed in PyCrypto 2.6. The 'IV' attribute in PyCrypto 2.5 and below returned a value that could be passed to the .new() parameter in order to restore its current state. In PyCrypto 2.6, this was changed to be the initial IV that was passed to the .new() parameter.

PyCrypto 2.5 and below:

    >>> from Crypto.Cipher import AES
    >>> ciph = AES.new("\0"*16, AES.MODE_CBC, "ABCDEFGHIJKLMNOP")
    >>> ciph.encrypt("\0"*16)
    'a\xd7\x82X\xeb\x1a\xbdo\xffG\x9d\x1d\xab\xb6\x10;'
    >>> ciph.IV
    'a\xd7\x82X\xeb\x1a\xbdo\xffG\x9d\x1d\xab\xb6\x10;'

PyCrypto 2.6:

    >>> from Crypto.Cipher import AES
    >>> ciph = AES.new("\0"*16, AES.MODE_CBC, "ABCDEFGHIJKLMNOP")
    >>> ciph.encrypt("\0"*16)
    'a\xd7\x82X\xeb\x1a\xbdo\xffG\x9d\x1d\xab\xb6\x10;'
    >>> ciph.IV
    'ABCDEFGHIJKLMNOP'

The new behavior violates PEP 272:

    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.

Also, despite what PEP 272 says, it was possible in PyCrypto 2.5 to modify the cipher's behavior by assigning to the 'IV' attribute. In PyCrypto 2.6, the assignment works, but has no effect.

Changed in pycrypto:
status: New → Confirmed
summary: - IV silently changed meaning in PyCrypto 2.6
+ IV silently changed meaning in PyCrypto 2.6; violates PEP 272
description: updated
Revision history for this message
Darsey Litzenberger (dlitz) wrote :

It looks like this bug was introduced when we added the Cipher.blockalgo.BlockAlgo wrapper class around all of the block ciphers: https://github.com/dlitz/pycrypto/commit/6f9fe103a582999c397f7bc8a2248613a207b780

description: updated
Revision history for this message
Legrandin (gooksankoo) wrote :

I don't think this is a bug: the PEP272 was not very well written on this topic.

If there was a way (I am not aware of any) it would be better to have the PEP272 fixed.

See my comments at the time the behavior changed:

https://github.com/dlitz/pycrypto/pull/13

"""
PEP272 says of IV that "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"

In this case, IV simply carries the initial value and never changes.

To me that's more logical (after all, intermediate states are not "initial" by definition).

Additionally, if PyCrypto had to ever use some backends like openssl, the internal state of the cipher is not guaranteed to be available.
"""

In addition to that, there is no consistent definition of what the "modified feedback text" could possibly be in all modes a cipher can be used in. There is nothing supporting the idea that .IV captures the full state of the cipher instance.
It is also quite dubious an application should even deal with the internal state of a cipher after it has started.

Revision history for this message
Darsey Litzenberger (dlitz) wrote :

Right, but PyCrypto is also used as a teaching tool in academia. The IV attribute is useful there. It can also be useful for ourselves, when implementing things like CMAC (which is how I discovered this bug in the first place).

In any case, the correct thing is either to remove the IV attribute, or preserve its original behavior, not to silently modify it as we did in the 2.6 release.

Revision history for this message
Legrandin (gooksankoo) wrote :

As soon as the value of the IV member changes, it is not the IV anymore so I am a bit puzzled by the educational value.
We are rather talking about one of the internal states of the cipher (and exactly which state strongly depends on the type of chaining mode).

On the other hand, it is also a misleading naming because sometimes I may need to know the original IV the cipher was initialized with and accessing cipher.IV is very intuitive.

Perhaps:
1. the IV member should be removed entirely as you say (easy)
2. a new get_IV() method introduced (easy)
3. some form of chaining-mode specific callback could be defined for those that want to monitor how the internal state changes for teaching purposes (more difficult)

As far as CMAC goes, there are cleaner ways to achieve the same result. ;-)

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.