Encoding/Decoding AES CTR between php and python
<p>I am connecting to an php API.
In their examples they encode everything with the following:</p>

<blockquote>
  <p>$data=AesCtr::encrypt($data, 'api_key_for_project', 256)</p>
</blockquote>

<p>I would like to connect via pythons pycrypto module and do the equivalent to the above.</p>

<p>I have tried a few different things although the server is unable to decode the message.</p>

<p>I know the 'counter' is not correct by being random however i cant think of an alternative.</p>

<pre><code>from Crypto.Cipher import AES

cipher = AES.new(api_key, AES.MODE_CTR, counter=lambda: os.urandom(16))
data = cipher.encrypt(b'{"name": "Test"}'))
</code></pre>

<p>Commonly, the counter values in CTR mode consist of:</p>

<ul>
<li>a prefix/nonce which must be unique for each message to be encrypted, but stays the same between blocks of one message. E.g. <code>os.urandom(8)</code> is a decent nonce (unless you encrypt more than about 2^32 messages with the same key).</li>
<li>the actual counter, which is 0 for the first block, 1 for the second, and so on.</li>
</ul>

<p>See <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29" rel="nofollow">Wikipedia</a> for an illustration and details. The prefix/counter split could be 96/32 bits, 64/64 bits, etc. Other variations, such as a postfix nonce, are possible but rare. Note that the receiver must learn the nonce somehow, the easiest way is to send it with the ciphertext (the nonce does not have to be encrypted).</p>

<p>So, how do you do this with pycrypto? Well, the <code>counter</code> function should be a stateful function (closure) that returns <code>prefix</code> plus the current counter value and increments the counter. Fortunately you don't have to write that yourself, pycrypto has a utility for it: <code>Crypto.Util.Counter</code>.</p>

<pre><code>import os
from Crypto.Cipher import AES
from Crypto.Util import Counter

nonce = os.urandom(8)
counter = Counter.new(64, prefix=nonce)
cipher = AES.new(api_key, AES.MODE_CTR, counter=counter)
data = nonce + cipher.encrypt(b'{"name": "Test"}')
</code></pre>

<p>Here, I prepended the nonce to the ciphertext. The receiver will need to strip the first 64 bits from the data and use them as the prefix for the counter.</p>

<p>I don't know how exactly the <code>AesCtr</code> PHP class is implemented. If it is the same as the one in <a href="http://stackoverflow.com/questions/10220271/php-class-declarations-may-not-be-nested">this question</a>, then it looks like it also prepends the 64-bit nonce to the ciphertext. So the above code might already Just Work (tm) for talking to the PHP API.</p>

<p>Side note: The <code>AesCtr</code> class from that question also creates a timestamp-based nonce instead of a completely random one (see <code>AesCtr::encrypt</code>), with the aim to ensure uniqueness. You could consider using the same approach to generate nonces.</p>

php python encryption