23

Is it possible to encrypt/decrypt data with AES without installing extra modules? I need to send/receive data from C#, which is encrypted with the System.Security.Cryptography reference.

UPDATE I have tried to use PyAES, but that is too old. I updated some things to make that work, but it didn't. I've also can't install because it latest version is 3.3 while my version is 3.4.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Anton
  • 542
  • 1
  • 6
  • 16
  • 1
    Sure, AES isn't that hard to do manually, if you don't mind it being slow. Or you can access the Windows crypto APIs via `ctypes`. Or `openssl`. But it would be a lot better to use a module that makes it easy. Is there a reason you don't want to? (Note that the [official documentation](https://docs.python.org/3.4/library/crypto.html) specifically points to [`pycrypto`](http://www.pycrypto.org/) for doing this kind of thing.) – abarnert Aug 12 '14 at 10:11
  • The `C#` part is working already, the problem is Python. I'm always having trouble installing Python modules so I would like it if there was a possibility to use AES without an extra module. The speed to en/decrypt can be at max 200ms, it is for a chat. – Anton Aug 12 '14 at 10:13
  • 7
    If you're having trouble installing Python modules, that's a problem you should solve, rather than ignoring it. If you have a broken Python installation, fix it or reinstall. If you don't know about [`pip`](https://pip.pypa.io/) or [Christoph Gohlke's Windows binary package repo](http://www.lfd.uci.edu/~gohlke/pythonlibs/), learn about them. – abarnert Aug 12 '14 at 10:14
  • Another possibility: Can you use IronPython instead of CPython? Then you can access `System.Security.Cryptography` just as easily from Python as from C#. – abarnert Aug 12 '14 at 10:18
  • 1
    pyaes seems to work fine with python 3.4 as of 2015/12/18, at least for simple use-cases (CTR encrypt/decrypt) – Giacomo Lacava Dec 18 '15 at 12:22

6 Answers6

16

I'm using Cryptography library.

Cryptography is an actively developed library that provides cryptographic recipes and primitives. It supports Python 2.6-2.7, Python 3.3+ and PyPy.

See this documentation for an example of how to use that library:

import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

# Pseudo-random key and initialisation vector
key = os.urandom(32)           # (32*8=256-bit. AES also accepts 128/192-bit)
init_vector = os.urandom(16)   # (16*8=128-bit. AES only accepts this size)

# Setup module-specific classes
cipher = Cipher(algorithms.AES(key), modes.CBC(init_vector))
encryptor = cipher.encryptor()
decryptor = cipher.decryptor()

# Encrypt and decrypt data
cyphertext = encryptor.update(b"a secret message") + encryptor.finalize()
plaintext = decryptor.update(cyphertext) + decryptor.finalize()
print(plaintext) # 'a secret message'

Some notes explaining the example code:

  • os.urandom is used for security instead of Python's random module. See this answer for more details.
  • This article has more details about why an initialisation vector is used and what CBC (Cypher Block Chaining) mode is in AES encryption.
  • The linked documentation explains classes specific to the cryptography module like algorithms or modes: "Cipher objects combine an algorithm such as AES with a mode like CBC or CTR."
  • Old versions of the library (<3.1) required a backend object. This is deprecated since version 36.0 of the library.
Madhav Malhotra
  • 385
  • 1
  • 5
  • 17
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
14

PYAES should work with any version of Python3.x. No need to modify the library.

Here is a complete working example for pyaes CTR mode for Python3.x (https://github.com/ricmoo/pyaes)

import pyaes

# A 256 bit (32 byte) key
key = "This_key_for_demo_purposes_only!"
plaintext = "Text may be any length you wish, no padding is required"

# key must be bytes, so we convert it
key = key.encode('utf-8')

aes = pyaes.AESModeOfOperationCTR(key)    
ciphertext = aes.encrypt(plaintext)

# show the encrypted data
print (ciphertext)

# DECRYPTION
# CRT mode decryption requires a new instance be created
aes = pyaes.AESModeOfOperationCTR(key)

# decrypted data is always binary, need to decode to plaintext
decrypted = aes.decrypt(ciphertext).decode('utf-8')

# True
print (decrypted == plaintext)

Let me know if you get any errors

Alecz
  • 1,951
  • 1
  • 19
  • 18
  • 1
    This was my favorite answer The pyaes is a library you can just place in your code without any installation. No need to install anything - just download and place in your project. – Gil Allen Jun 21 '22 at 10:29
  • FYI: PYAES has the MIT license (for those who don't want to follow the link to check). – Brōtsyorfuzthrāx Oct 24 '22 at 23:11
9

The available Cryptographic Services available in the Standard Library are those. As you can see AES is not listed, but is suggest to use pycrypto which is an extra module.

You just have to install it using pip, or easy_install and then as showed in pycrypto's page:

from Crypto.Cipher import AES
obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
message = "The answer is no"
print obj.encrypt(message)

The only other way without using an extra module would be to code the function yourself, but what's the difference of downloading an extra module and use that instead?

If you want a pure Python implementation of AES that you can download and import check pyaes.

enrico.bacis
  • 30,497
  • 10
  • 86
  • 115
  • Well, an extra module that you write yourself, in pure Python, and leave in the same project directory as the main script can be a way around "having trouble installing modules". Not necessarily a _good_ way, but it's certainly different from installing `pycrypto`. – abarnert Aug 12 '14 at 10:17
  • What I say in the answer is that you could also download the full *pycrypto* source and place it *next to* your code, if you don't want (or can not) install modules. – enrico.bacis Aug 12 '14 at 10:20
  • 1
    That only works for pure-Python packages; PyCrypto is mostly C extensions that you have to build. – abarnert Aug 12 '14 at 10:34
  • [This](http://www.voidspace.org.uk/python/modules.shtml#pycrypto) only goes till Python `3.3` while I'm having Python `3.4` – Anton Aug 13 '14 at 19:37
  • That ain't working either, the version is [also to old](http://kutj.es/454-s6). Or you think it will work if I fix the print()? – Anton Aug 13 '14 at 21:34
  • I've updated some code, but this is for encrypting files, not just text. I think I can make it working with some editing. – Anton Aug 13 '14 at 21:54
  • Not working this way, I'm overloaded with errors (because of the wrong version, I assume) – Anton Aug 13 '14 at 22:34
4

Here is a self-contained implementation of AES compatible with Python 3.

Example usage:

aesmodal = AESModeOfOperation() 
key = [143,194,34,208,145,203,230,143,177,246,97,206,145,92,255,84]
iv = [103,35,148,239,76,213,47,118,255,222,123,176,106,134,98,92]

size = aesmodal.aes.keySize["SIZE_128"]

mode,orig_len,ciphertext = aesmodal.encrypt("Hello, world!", aesmodal.modeOfOperation["OFB"], key, size, iv)
print(ciphertext)
plaintext = aesmodal.decrypt(ciphertext, orig_len, mode, key, size, iv)
print(plaintext)
snowcrash09
  • 4,694
  • 27
  • 45
3

To add to @enrico.bacis' answer: AES is not implemented in the standard library. It is implemented in the PyCrypto library, which is stable and well tested. If you need AES, add PyCrypto as a dependency of your code.

While the AES primitives are, in theory, simple enough that you could write an implementation of them in pure Python, it is strongly recommended that you not do so. This is the first rule of crypto: don't implement it yourself. In particular, if you're just rolling your own crypto library, you'll almost certainly leave yourself open to some kind of side-channel attack.

MSmedberg
  • 381
  • 3
  • 13
2

Python 3.6 with cryptography module

from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
token = f.encrypt(b"my deep dark secret")
print(token)


f.decrypt(token)
Saurabh Chandra Patel
  • 12,712
  • 6
  • 88
  • 78