Skip to content
This repository has been archived by the owner on Jan 27, 2022. It is now read-only.

IV is tested for AES but it shouldn't #149

Open
palmkevin opened this issue Jul 22, 2015 · 7 comments
Open

IV is tested for AES but it shouldn't #149

palmkevin opened this issue Jul 22, 2015 · 7 comments

Comments

@palmkevin
Copy link

In the AES-documentation, you state that IV is "ignored for MODE_ECB and MODE_CTR" (source)
But currently you get the error message "CTR mode needs counter parameter, not IV" when the AES cipher is used.
For more information, see this thread posted by another user (For me his workaround is working too)

@haridsv
Copy link

haridsv commented Aug 3, 2015

I am hitting this while using paramiko to connect to any machine in our environment (tried so far: RHEL6.6, Mac OS X 10.10.4, Solaris 10). I tried the workaround suggested in the linked thread and it got me through.

@DakotaNelson
Copy link

I'm hitting this as well in Python 3.3.3 using paramiko.

Traceback (most recent call last):
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1610, in run
    self.kex_engine.parse_next(ptype, m)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/kex_group1.py", line 74, in parse_next
    return self._parse_kexdh_reply(m)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/kex_group1.py", line 111, in _parse_kexdh_reply
    self.transport._activate_outbound()
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1909, in _activate_outbound
    engine = self._get_cipher(self.local_cipher, key_out, IV_out)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1524, in _get_cipher
    return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv, counter)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/AES.py", line 180, in new
    return AESCipher(key, *args, **kwargs)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/AES.py", line 113, in __init__
    blockalgo.BlockAlgo.__init__(self, _AESNI, key, *args, **kwargs)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/blockalgo.py", line 398, in __init__
    self._cipher = factory.new(key, *args, **kwargs)
ValueError: CTR mode needs counter parameter, not IV

Traceback (most recent call last):
  File "testdeploy.py", line 9, in <module>
    s.connect(host, username='root', key_filename=keypath)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/client.py", line 265, in connect
    t.start_client()
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 406, in start_client
    raise e
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1610, in run
    self.kex_engine.parse_next(ptype, m)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/kex_group1.py", line 74, in parse_next
    return self._parse_kexdh_reply(m)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/kex_group1.py", line 111, in _parse_kexdh_reply
    self.transport._activate_outbound()
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1909, in _activate_outbound
    engine = self._get_cipher(self.local_cipher, key_out, IV_out)
  File "/home/.../venv/lib/python3.3/site-packages/paramiko/transport.py", line 1524, in _get_cipher
    return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv, counter)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/AES.py", line 180, in new
    return AESCipher(key, *args, **kwargs)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/AES.py", line 113, in __init__
    blockalgo.BlockAlgo.__init__(self, _AESNI, key, *args, **kwargs)
  File "/home/.../venv/lib/python3.3/site-packages/Crypto/Cipher/blockalgo.py", line 398, in __init__
    self._cipher = factory.new(key, *args, **kwargs)
ValueError: CTR mode needs counter parameter, not IV
paramiko==1.15.2
pycrypto==2.7a1

I'm using the edge version of pycrypto, and an older version of paramiko, which is perhaps part of the issue.

@conz27
Copy link

conz27 commented Sep 17, 2015

I took a look at the history of when the exception handling was introduced for ValueError: CTR mode needs counter parameter, not IV, which is in commit 8dbe0dc.

I think the original author @Legrandin made a good decision to raise an exception when incorrect AES parameters are being passed in. When using AES in CTR mode, the IV should not be specified because it's not actually used in the encryption process; therefore, paramiko should not be passing it in. I think the module is behaving as designed and the documentation is out-of-date.

Developers using pycrypto should understand how to use it correctly. If they make incorrect assumptions and assume certain parameters are being used but in fact are not - they can inadvertently cause security holes or cryptographic weaknesses.

I recommend:

  • close this bug and open an issue against paramiko to address cases where pycrypto is incorrectly used in regards to AES in CTR mode
  • open a documentation bug against pycrypto to specify that the IV is not actually ignored when used with CTR mode, but should never be specified and will result in an exception

NOTE: The workaround works because the IV length is zero; hence the check passes because IVlen == 0 when you re-create the AESCipher object.

@mouse07410
Copy link

It is not that simple. The parameter in CTR mode is comprised of a counter field (that doesn't necessarily start from zero or one) and an "IV" field filled with (pseudo) random bits (at least when implemented properly). It should be possible to feed this object through the IV parameter, with explicit understanding that a part of that value will be used as a counter.

Sent from my iPad

On Sep 16, 2015, at 23:36, Constantine Grantcharov <notifications@github.commailto:notifications@github.com> wrote:

I took a look at the history of when the exception handling was introduced for ValueError: CTR mode needs counter parameter, not IV, which is in commit 8dbe0dchttps://github.com/dlitz/pycrypto/commit/8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4.

I think the original author @Legrandinhttps://github.com/Legrandin made a good decision to raise an exception when incorrect AES parameters are being passed in. When using AES in CTR mode, the IV should not be specified because it's not actually used in the encryption process; therefore, paramiko should not be passing it in.

Developers using pycrypto should understand how to use it correctly. If they make incorrect assumptions and assume certain parameters are being used but in fact are not - they can inadvertently cause security holes or cryptographic weaknesses.

I recommend:

  • close this bug and open an issue against paramiko to address cases where pycrypto is incorrectly used in regards to AES in CTR mode
  • open a documentation bug against pycrypto to specify that the IV is not actually ignored when used with CTR mode, but should never be specified and will result in an exception


Reply to this email directly or view it on GitHubhttps://github.com//issues/149#issuecomment-140959951.

@conz27
Copy link

conz27 commented Sep 17, 2015

I agree that what you're suggesting is possible from a programming perspective, where the IV parameter can be used as the counter in CTR mode. To fix the bug, your proposal would work.

However, from a conceptual purity perspective, AES-CTR does not use an IV - it uses a counter. I'd argue that letting the user pass the counter via the IV parameter to would be confusing conceptually and deviates from existing documentation on CTR mode. Just my opinion though.

@mouse07410
Copy link

IMHO this conceptual purity is flawed from cryptographic point of view, because in the field a "pure" counter without an "IV" component is bad. So I personally find a "pure" counter implementation all but useless.

The real question is what kind of interface (and documentation) should an implementation present to ensure that the provided parameter field is used appropriately in different modes. It matters less what you call this parameter (an IV, a counter, a byte string, a scarecrow), because in the end you have a cipher black box construct that takes plaintext, key, and one parameter that is interpreted differently depending on the cipher mode AND THE SPECIFIC IMPLEMENTATIONS of that mode (for example, some implementations I've seen increment the "counter" part of the parameter modulo 2^32, ensuring that the rest of the parameter stays in act/unchanged from block to block). Regardless, it seems obvious that purist or not, according to the specs the user is allowed to provide any value of the "counter" to start with - it does NOT have to start from 0 or 1. So I fail to see how providing any 128-bit value (16 bytes) as a parameter to AES-CTR is in any way inappropriate.

Sent from my iPad

On Sep 17, 2015, at 01:19, Constantine Grantcharov <notifications@github.commailto:notifications@github.com> wrote:

I agree that what you're suggesting is possible from a programming perspective, where the IV parameter can be used as the counter in CTR mode. To fix the bug, your proposal would work.

However, from a conceptual purity perspective, AES-CTR does not use an IV - it uses a counter. I'd argue that letting the user pass the counter via the IV parameter to would be confusing conceptually and deviates from existing documentation on CTR mode. Just my opinion though.


Reply to this email directly or view it on GitHubhttps://github.com//issues/149#issuecomment-140972258.

@conz27
Copy link

conz27 commented Sep 18, 2015

IMHO this conceptual purity is flawed from cryptographic point of view, because in the field a "pure" counter without an "IV" component is bad. So I personally find a "pure" counter implementation all but useless.

CTR mode does not technically use an IV, it uses a nonce in conjunction with a counter. In the context of block cipher modes IV and nonce sometimes can mean the same thing. Your use of IV instead of nonce is what lead to some confusion on my part; but, in CTR mode they are equivalent like you said.

I had a brief discussion with my co-workers today about this - I work for cryptography company. The consensus was that proper naming conventions SHOULD be followed because there are subtle differences in how these parameters are used and how they are generated that could lead to cryptographic weaknesses.

IV:

  • typically pseudo-random generated value of some length
  • generate this value using non-deterministic or unpredictable methods (i.e. /dev/random on Linux)

Nonce:

  • a generated value of some length
  • should be used only once with a given key
  • an IV can be nonce, but nonces can also be generated deterministically and still provide cryptographic integrity (i.e. a shift register incrementing a value by one can be used to generate nonces)

Counter:

  • a generated value of some length, which is usually incremented per encryption block (for multi-block encryptions/decryptions)
  • guaranteed not to repeat for a long time

So, using the above definitions ... AES-CTR uses a nonce (static for all encryption/decryption blocks) and incrementing counter instantiated at some initial value. Like you said @mouse07410, the random IV CAN be used a nonce.

It matters less what you call this parameter (an IV, a counter, a byte string, a scarecrow)

I still maintain that using properly named parameters in the pycrypto code would enable users to make smarter decisions in how they use the library and guard against unintended consequences. For example, saying that AES-CTR can work with just a long random IV where one part is the nonce and the other is the counter's base value is technically true. But calling that parameter an IV implies it has to be unpredictable hence placing an unnecessary requirement to use a PRNG. This misunderstanding can in turn lead to slower applications because using /dev/random as a PRNG in embedded environments can actually take a long time due to low entropy or imply that special hardware is required for randomness when that is actually not true.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants