pyaes and the relationship between byte and str in Python 3?
<p>I'm trying to use pyaes (<a href="https://github.com/ricmoo/pyaes/blob/master/README.md" rel="nofollow">https://github.com/ricmoo/pyaes/blob/master/README.md</a>) in Python 3 to encrypt and decrypt text using pyaes. When I encrypt text, I give pyaes a <code>str</code> value i.e.</p>

<pre><code>plaintext = 'plain text'
key = os.urandom(16)
aes = pyaes.AESModeOfOperationCTR(key)
ciphertext = aes.encrypt(plaintext)
</code></pre>

<p>when I decrypt though, I get back a <code>bytes</code> type:</p>

<pre><code>aes = pyaes.AESModeOfOperationCTR(key)
decrypted_plaintext = aes.decrypt(ciphertext)
</code></pre>

<p>Printing <code>decrypted_plaintext</code> produces the following output, which seems to contain the original text:</p>

<pre><code>b'plain text'
</code></pre>

<p>But its not quite the same; one is a <code>str</code> the other is a <code>bytes</code>:</p>

<pre><code>plaintext == decrypted_plaintext # False
</code></pre>

<p>I'm struggling to understand the relationship between <code>bytes</code> and whatever Python 3's internal representation of <code>str</code> is. How do I convert the <code>bytes</code> type into <code>str</code> to get my plaintext? </p>

<p>I have confirmed that running the examples on the pyaes readme page have the same problem. I'm guessing that is going to be something to do with encodings.</p>

<p>In Python 3 <code>str</code> type represents a string in unicode format. It is composed of relatively abstract codepoints, that is numbers coding characters.
There are several ways to transform (encode) those codepoints to actual bytes which are known as "encodings". utf-8 and utf-16 are some encodings which allow to encode unicode characters.</p>

<p><em>Note that some encoding (as ASCII) does <strong>not</strong> allow to encode unicode characters.</em></p>

<p>When you encode a <code>str</code> string in Python, you obtain a list of bytes of type <code>bytes</code>. You can then decode this list of bytes to get a <code>str</code>string.</p>

<p>The point to keep in mind is that you have to specify an encoding to encode a <code>str</code> string and you have to know the encoding of a <code>bytes</code>string to be able to decode it. If you don't specify encoding, Python will try to encode and decode with its default encoding and you could obtain "random" results.</p>

<p>In you specific case, the difference is not visible because all the characters of your strings are ASCII chars and, fortunately, the 128 first codepoints of unicode match the ASCII table.</p>

<p>Try to introduce some 'exeotic' characters (like Ã©, Ã§ or Ã) in your string and you will see a difference.</p>

<hr>

<p>Now, pyaes does not encrypt/decrypt unicode codepoints but bytes.
So you have to encode the strings you encrypt and you have to know the used encoding to decode the decrypted strings.</p>

<hr>

<p>More information in the Python doc:</p>

<ul>
<li><a href="https://docs.python.org/3/library/stdtypes.html#bytes" rel="nofollow">bytes</a></li>
<li><a href="https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str" rel="nofollow">str</a></li>
<li><a href="https://docs.python.org/3/reference/lexical_analysis.html#strings" rel="nofollow">strings and bytes litterals</a></li>
</ul>

python encryption