0

Here's my code:

Encrypt:

from Crypto.Cipher import AES
import base64

def encryption (privateInfo):
    BLOCK_SIZE = 16
    PADDING = '{'
    pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
    EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
    secret = 'Fr3@k1nP@ssw0rd.'
    print('encryption key:', secret)
    cipher = AES.new(secret)
    encoded = EncodeAES(cipher, privateInfo)
    print('Encrypted string:', encoded)

encryption('secret')

The encrypted string is: b'QuCzNmwiVaq1uendvX7P+g=='

Decrypt:

from Crypto.Cipher import AES
import base64

def decryption(encryptedString):
    PADDING = '{'
    DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
    key = 'Fr3@k1nP@ssw0rd.'
    cipher = AES.new(key)
    decoded = DecodeAES(cipher, encryptedString)
    print(decoded)

decryption("b'QuCzNmwiVaq1uendvX7P+g=='")

The result:

ValueError: Input strings must be a multiple of 16 in length

This is PyCrypto 2.6.1 on Python 3.4; I've installed VC++ 2010 Express as well. What's really confusing me is that it works perfectly on Python 2.7

Any suggestion appreciated, but note that I'm new to Python.

linusg
  • 6,289
  • 4
  • 28
  • 78
  • 1
    Why do you need VC++ for this? – linusg Apr 01 '16 at 19:10
  • 1
    you have error in last line, should be: decryption("QuCzNmwiVaq1uendvX7P+g==") – scope Apr 01 '16 at 19:17
  • I'm really not sure @linusg It seems that there might be some errors when installing pycrypto. It looks for Visual C++ files. It is VC++ 2010 after Python 3.3 so some people suggest to install it. I don't know what's the reason or weather it might have something to do after installation. Maybe it does, so I pointed that out. –  Apr 01 '16 at 19:24
  • I'm getting "TypeError: 'str' does not support the buffer interface" @scope –  Apr 01 '16 at 19:25
  • @GlebG Ah OK, thanks for information. I think I used an installer for PY2.7, but I had problems with installing it on PY3.x too (I hadn't figured it out yet...). – linusg Apr 01 '16 at 19:26
  • 1
    Actually I wasn't able to install it any other way so I used an installer as well: https://github.com/axper/python3-pycrypto-windows-installer @linusg –  Apr 01 '16 at 19:29
  • Thanks! That did it! – linusg Apr 01 '16 at 19:31
  • It 'd be great to know if you're able to decrypt your encrypted strings @linusg Otherwise maybe there's something wrong with the installer so I'll have to install other 3.x Pythons to try to make pycrypto work on Python3. –  Apr 01 '16 at 19:51
  • I'll post an answer in a minute, I'm searching for the code I've written some time ago. BTW, please accept the edit I made to your question. – linusg Apr 01 '16 at 19:58
  • Sorry, I've found it, but it has problems running on PY3x... I'll try it tomorrow – linusg Apr 01 '16 at 20:22
  • 1
    **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Apr 02 '16 at 16:12

2 Answers2

1

After some research and a lot of coding, testing and improving, I made this code running on Python 3.4.4 and Windows 10:

import base64
from Crypto.Cipher import AES
from Crypto.Hash import SHA256

PAD = "X"

def key_hash(key):
    return SHA256.new(key.encode()).digest()

def encrypt(text, key):
    while len(text) % 16 != 0:
        text += PAD
    cipher = AES.new(key_hash(key))
    encrypted = cipher.encrypt(text.encode())
    return base64.b64encode(encrypted).decode()

def decrypt(text, key):
    cipher = AES.new(key_hash(key))
    plain = cipher.decrypt(base64.b64decode(text))
    return plain.decode().rstrip(PAD)

if __name__ == '__main__':
    e = encrypt("This is my string.", "password")
    p = decrypt(e, "password")
    print("Encrypted:", e)
    print("Plain:", p)

Output:

Encrypted: QjkhFlXG2tklZQgHorpAOFSTb2vYZLNb/eEUIvAsT1g=
Plain: This is my string.

If you have any questions/improvements/critics, feel free to comment!

linusg
  • 6,289
  • 4
  • 28
  • 78
  • That works great! And it is a lot simpler than anything else I've tried on Python3 so far. Thanks! –  Apr 04 '16 at 20:43
0

Maybe because you have " around "b'QuCzNmwiVaq1uendvX7P+g=='".

Change

decryption("b'QuCzNmwiVaq1uendvX7P+g=='")

to

decryption(b'QuCzNmwiVaq1uendvX7P+g==')

and you should be all set.

linusg
  • 6,289
  • 4
  • 28
  • 78
Vor
  • 33,215
  • 43
  • 135
  • 193
  • I'm getting: TypeError: 'str' does not support the buffer interface –  Apr 01 '16 at 19:27
  • 1
    @GlebG It's pretty clear that there is a mismatch between str and bytes. The fix would be to add `.decode()` here: `c.decrypt(base64.b64decode(e)).decode().rstrip(PADDING)`. (@Vor feel free to include that in your answer.) – Artjom B. Apr 02 '16 at 16:10