Workaround for: CTR mode needs counter parameter, not IV

After upgrading the local Linux system, my python paramiko (ssh protocol implementation) program stopped working, with the error message:

CTR mode needs counter parameter, not IV

Internet search gave no solution. Therefore, it was a time to experiment.

A logical consequence from the error message is that somewhere should be used only "IV" or only "counter", but not both. With a stack trace, a candidate is found. A function _get_cipher in transport.c of paramiko.

elif name.endswith("-ctr"):
    # CTR modes, we need a counter
    counter = Counter.new(nbits=self._cipher_info[name]['block-size'] * 8, initial_value=util.inflate_long(iv, True))
    return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv, counter)

Trying to set iv to None. Another error. Setting to an empty string. It works!

Current solution

The easiest way for _me_ is to hook into the new function. Something like this:

import Crypto.Cipher.AES
orig_new = Crypto.Cipher.AES.new
def fixed_AES_new(key, *ls):
  if Crypto.Cipher.AES.MODE_CTR == ls[0]:
    ls = list(ls)
    ls[1] = ''
  return orig_new(key, *ls)

import paramiko

t = paramiko.Transport((host, 22))
try:
  t.connect(username=username, password=password)
except ValueError, e:
  print e
  print '! second attempt'
  t.close()
  t = paramiko.Transport((host, 22))
  Crypto.Cipher.AES.new = fixed_AES_new
  t.connect(username=username, password=password)
print "password is ok"
t.close()

Who to blame?

The question is hard. On one side, it is indeed paramiko who should drop iv. On the other side, how the generic code can know that in some cases new requires iv and in other cases (AES) does not?

In any case, AES.py from pycrypto says:

IV : byte string ...
It is ignored for `MODE_ECB` and `MODE_CTR`.

It is false now.

My intuition says that the old behaviour (indeed ignore iv) should be returned back.

Categories: python

Updated: