Fernet is a recipe that implements the Fernet specification (https://github.com/fernet/spec/blob/master/Spec.md). Accordingly you will only be able to use it to decrypt things that have been encrypted with other libraries that utilize that specification. At this time there's no (official) way to derive a Fernet key from a passphrase (although you could look at how Fernet keys are generated and use the KDF primitives to accomplish such a thing).
If you supply your PyCrypto code we can more clearly understand what you're trying to accomplish, but in the absence of that here are some avenues of inquiry to pursue...
openssl enc derives keys and IVs from passphrases in its own special way (see:?http://security.stackexchange.com/questions/29106/openssl-recover-key-and-iv-by-passphrase). You are correct in thinking you need to use the hazmat APIs to do this decryption (assuming you have a hard requirement of being able to decrypt data encrypted using the openssl enc utility). To accomplish that you'll need to write some code that can replicate the EVP_BytesToKey (https://www.openssl.org/docs/crypto/EVP_BytesToKey.html) call that enc uses (https://github.com/openssl/openssl/blob/master/apps/enc.c#L569). The implementation of that function can be found here (https://github.com/openssl/openssl/blob/e0fc7961c4fbd27577fb519d9aea2dc788742715/crypto/evp/evp_key.c#L115). If the user leaves everything default this function is the equivalent of MD5(password+salt)
If, on the other hand, you just generically want to be able to encrypt data and have it be decrypted by libraries in other languages you can either use Fernet (and decrypt it with something like?https://github.com/fernet/fernet-rb,?https://github.com/fernet/fernet-go, or?https://github.com/dreid/fernet-clj) or generate a key/iv yourself (using os.urandom) and then use them to encrypt. Looking through our docs we appear to be missing an example of this using our padding functions with our encryptor/decryptor so here you go:
padder = padding.PKCS7(algorithms.AES.block_size).padder()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
encryptor = cipher.encryptor()
# this next line is all in one, but if you're streaming large volumes of data you'd split
# it up to make as many update calls as needed
ct = encryptor.update(padder.update(data) + padder.finalize()) + encryptor.finalize()
To decrypt you'll need the ct, IV, and key. Of course, this isn't authenticated encryption (which you get with Fernet or an AEAD mode like GCM) so you'll either need to add an HMAC to this or switch to GCM if you want to have confidence in the message integrity. (This is why constructs like Fernet are valuable and why we recommend them over rolling your own if possible).
On January 2, 2015 at 8:00:45 PM, David Evans (djve60 at gmail.com) wrote:
I'm playing with the Fernet and AES encryption from cryptography. I've only started with Python a few weeks ago and I'm not up on cryptography.
I'm trying to decrypt data that has been encoded with OpenSSL. I can decode it with python 2.7 using Crypto.Cipher but I'm having problems getting cryptography to do the same thing.
? ?key = Fernet.generate_key()
will generate a new key is there a way to generate a valid key from an existing passphrase?
? ?openssl enc -base64?
produces a key that is too small. Does this need to be padded with NULLs or is there a command I'm missing?
I'd prefer documentation that will bring me up to speed on this area rather than example code. The November thread on signatures and keys didn't address my simplistic issue.
I have tried using the lower level "Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)" but my decryptor generates and error but this due to my sending a str and not bytes.