mervick / aes-everywhere

Aes Everywhere - Cross Language AES 256 Encryption Library (Bash, Powershell, C#, Dart, GoLang, Java, JavaScript, Lua, PHP, Python, Ruby, Swift)
Other
474 stars 169 forks source link

(Python) How to implement #7

Closed AzriDelta closed 5 years ago

AzriDelta commented 5 years ago

Sorry for raising another issue, it may look trivial, but I have no idea to solve it.

I tried to implement the Python version by downloading aes256.py and creating a testing.py (both files are in the same folder).

For testing.py, I use the same code just like in the README.md

import aes256 from aes256

# encryption
print(aes256.encrypt('TEXT', 'PASSWORD'))

# decryption
print(aes256.decrypt('ENCRYPTED', 'PASSWORD'))

but it raises the error

import aes256 from aes256
SyntaxError: invalid syntax`

with the '^' symbol pointing to the letter 'm' of 'from'.

What I did was to modify the code to this:

import aes256 

aes256_v = aes256.aes256()

# encryption
print(aes256_v.encrypt('TEXT', 'PASSWORD'))

# decryption
print(aes256_v.decrypt('ENCRYPTED', 'PASSWORD'))

but now the error that appeared was

Traceback (most recent call last):
  File "<mydirectory>/Python Testing/testing.py", line 6, in <module>
    print(aes256_v.encrypt('TEXT', 'PASSWORD'))
  File "<mydirectory>\Python Testing\aes256.py", line 39, in encrypt
    return base64.b64encode(b'Salted__' + salt + cipher.encrypt(self.__pkcs5_padding(raw)))
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 160, in encrypt
    expect_byte_string(plaintext)
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Util\_raw_api.py", line 172, in expect_byte_string
    raise TypeError("Only byte strings can be passed to C code")
TypeError: Only byte strings can be passed to C code

I use VSCode and Python 3.6.3

mervick commented 5 years ago

Sorry, my fault, copy aes256.py in the same folder with your testing.py and use this code

from aes256 import aes256

# encryption
encrypted = aes256().encrypt('TEXT', 'PASSWORD')
print(encrypted)

# decryption
print(aes256().decrypt(encrypted, 'PASSWORD'))
AzriDelta commented 5 years ago

The same error still happening, even after using the above code

Traceback (most recent call last):
  File "<mydirectory>/Python Testing/testing.py", line 4, in <module>
    encrypted = aes256().encrypt('TEXT', 'PASSWORD')
  File "<mydirectory>\Python Testing\aes256.py", line 39, in encrypt
    return base64.b64encode(b'Salted__' + salt + cipher.encrypt(self.__pkcs5_padding(raw)))
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 160, in encrypt
    expect_byte_string(plaintext)
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Util\_raw_api.py", line 172, in expect_byte_string
    raise TypeError("Only byte strings can be passed to C code")
TypeError: Only byte strings can be passed to C code

A little bit reading on _mode_cbc.py, it looks it requires byte string, but it's getting string returned from pkcs5_padding(raw).

UPDATE: I add the following lines of code at __pkcs5_padding() for 'aes256.py' to replace the return statement as below:

s = s + (self.BLOCK_SIZE - len(s) % self.BLOCK_SIZE) * chr(self.BLOCK_SIZE - len(s) % self.BLOCK_SIZE)
b = bytes(s, 'utf-8')
return b

and it works.

By following the sample code, it should return the statement as below

b'U2FsdGVkX18DbtQ7JRk3E+QZnxckBINY9cZVaMZ3Ghk='
b'TEXT'

Attached is the modified aes256.py and testing.py for your testing. aes256 testing.zip

mervick commented 5 years ago
from aes256 import aes256

# encryption
encrypted = aes256().encrypt('TEXT', b'PASSWORD')
print(encrypted)

# decryption
print(aes256().decrypt(encrypted, b'PASSWORD'))
mervick commented 5 years ago

Also try to add encoding in your testing.py at the beginning of the file

#!/usr/bin/env python
# -*- coding: utf-8 -*-
AzriDelta commented 5 years ago

Using the given sample code, this error pops out

Traceback (most recent call last):
  File "d:/Google Drive/UM/UM Sem 7/#IPPI/#Sem 7/Coding and Testing/Python Testing/testing.py", line 7, in <module>
    encrypted = aes256().encrypt('TEXT', b'PASSWORD')
  File "d:\Google Drive\UM\UM Sem 7\#IPPI\#Sem 7\Coding and Testing\Python Testing\aes256.py", line 37, in encrypt
    key, iv = self.__derive_key_and_iv(passphrase, salt)
  File "d:\Google Drive\UM\UM Sem 7\#IPPI\#Sem 7\Coding and Testing\Python Testing\aes256.py", line 93, in __derive_key_and_iv
    d_i = md5(d_i + password.encode('utf-8') + salt).digest()
AttributeError: 'bytes' object has no attribute 'encode'

So, if I changed d_i = md5(d_i + password.encode('utf-8') + salt).digest() to d_i = md5(d_i + password + salt).digest() now this error happens:

Traceback (most recent call last):
  File "<mydirectory>/Python Testing/testing.py", line 7, in <module>
    encrypted = aes256().encrypt('TEXT', b'PASSWORD')
  File "<mydirectory>\Python Testing\aes256.py", line 39, in encrypt
    return base64.b64encode(b'Salted__' + salt + cipher.encrypt(self.__pkcs5_padding(raw)))
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 160, in encrypt
    expect_byte_string(plaintext)
  File "C:\Users\<myname>\AppData\Local\Programs\Python\Python36\lib\site-packages\Crypto\Util\_raw_api.py", line 172, in expect_byte_string
    raise TypeError("Only byte strings can be passed to C code")
TypeError: Only byte strings can be passed to C code
mervick commented 5 years ago

Okey, I updated aes256.py, try it now

AzriDelta commented 5 years ago

It works.

b'U2FsdGVkX18RTb+muaFK+NXQuNpZa6EFDCOVT6vd4ng='
b'TEXT'

and second attempt produced this:

b'U2FsdGVkX1/eGk5cX+Bh0ZIezVVZXQgui3S+txk2Z1k='
b'TEXT'

These are correct right? New encrypted value for each attempt even though the plaintext is the same?

mervick commented 5 years ago

Yes, it's correct, it uses random salt for security reason