1

I am having difficulty with AES-CTR encryption using pycryptodome on Python 3. Data can be ~1000 bytes but when it gets long enough it breaks. I do not understand what this error supposedly means or how to get around it.

from os import urandom
from Crypto.Cipher import AES

cipher = AES.new(urandom(16), AES.MODE_CTR, nonce=urandom(15))
cipher.encrypt(urandom(10000))

---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-116-a48990362615> in <module>()
      3 
      4 cipher = AES.new(urandom(16), AES.MODE_CTR, nonce=urandom(15))
----> 5 cipher.encrypt(urandom(10000))
      6 

/usr/local/lib/python3.5/dist-packages/Crypto/Cipher/_mode_ctr.py in encrypt(self, plaintext)
    188         if result:
    189             if result == 0x60002:
--> 190                 raise OverflowError("The counter has wrapped around in"
    191                                     " CTR mode")
    192             raise ValueError("Error %X while encrypting in CTR mode" % result)

OverflowError: The counter has wrapped around in CTR mode
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
ArekBulski
  • 4,520
  • 4
  • 39
  • 61

1 Answers1

1

I figured it out. Nonce is only 1 byte short of block size so counter mode can only produce 256 blocks which would allow to encrypt 4096 bytes. If nonce is few bytes shorter the problem goes away.

ArekBulski
  • 4,520
  • 4
  • 39
  • 61
  • 1
    The [documentation for that constructor](https://legrandin.github.io/pycryptodome/Doc/3.4/Crypto.Cipher.AES-module.html) recommends 8 bytes for the nonce in CTR mode. The overflow behavior seems pretty silly to me, though: it'd make more sense to just pass a 16-byte random IV, instead of splitting it into separate `nonce` and `initial_value` parts. But this library doesn't allow the `iv` argument in CTR mode. – Wyzard Apr 18 '17 at 02:03
  • It makes total sense, it detects an situation where same counter was used more than once which is considered a security breach. – ArekBulski Apr 18 '17 at 05:34
  • 1
    Not quite. It divides up the counter space into smaller chunks and prevents overflow from one chunk into another, which prevents collisions *if* you use a different chunk (nonce) every time. But it doesn't prevent or detect re-use of nonces, and if you're choosing your nonce randomly, the chance of collision is increased because only some of the counter's bits (the `nonce` part) are random and the rest (the `initial_value` part) are zero. You'd be better off just initializing the whole counter with 16 random bytes. – Wyzard Apr 18 '17 at 06:06