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.


Q:
While
    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.


FYI:
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.


Many thanks,


David


--
=========================
Your reason is treason. Kasabian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20150102/cf2826cd/attachment.html>

Search Discussions

  • Paul Kehrer at Jan 3, 2015 at 2:50 am
    Hi David,


    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).


    -Paul Kehrer


    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.


    Q:
    While
    ? ?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.


    FYI:
    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.


    Many thanks,


    David


    --
    =========================
    Your reason is treason. Kasabian
    _______________________________________________
    Cryptography-dev mailing list
    Cryptography-dev at python.org
    https://mail.python.org/mailman/listinfo/cryptography-dev
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20150102/1cc22717/attachment.html>
  • David Evans at Jan 5, 2015 at 6:05 pm
    I found the answer to what I was trying to find at ?
    http://incolumitas.com/2014/10/19/using-the-python-cryptography-module-with-custom-passwords/
    when following up on the URLs.


    In case the site goes off line the code I was after is just (copied from
    the site) by Nikolai Tschacher:
    import base64
    from cryptography.fernet import Fernet
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.backends import default_backend


    def get_key(password):
         digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
         digest.update(password)
         return base64.urlsafe_b64encode(digest.finalize())


    def encrypt(password, token):
         f = Fernet(get_key(key))
         return f.encrypt(bytes(token))


    def decrypt(password, token):
         f = Fernet(get_key(password))
         return f.decrypt(bytes(token))


    but the problem I have with this is using a non-randomized password helps
    subvert the security of the 32-bit random password that Fernet provides.
    However, as Nikolai notes, it's more usable for interactive activities.


    For new code I'll be using Fernet but for existing code I think I'm forced
    to keep to PyCrypto. Since a Fernet message is a self-signed (a little like
    a PKCS12 type file) it will not be appropriate for many existing processes
    but I think it should be used where possible.


    Thanks for the help,


    David
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20150105/6b09a5dc/attachment.html>
  • Paul Kehrer at Jan 5, 2015 at 6:26 pm
    Thanks for the update David.


    I'd strongly recommend against using that construction as it is just doing a single SHA256 hash of your password and then base64 encoding it. While a password is definitely lower entropy than 32 bytes of random you can still derive a key suitable for encryption from a password by using a KDF (key derivation function). KDFs are useful in this context because they raise the cost of computing the key so that an attacker can't easily brute force the password. Consider replacing the get_key function with something using PBKDF2HMAC (https://cryptography.io/en/latest/hazmat/primitives/key-derivation-functions/#cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC). An even better KDF would be something like scrypt, but unfortunately we don't support that in pyca/cryptography yet.


    This definitely is showing a need for an official password-based encryption key derivation for Fernet...


    -Paul Kehrer
    On January 5, 2015 at 12:07:31 PM, David Evans (djve60 at gmail.com) wrote:


    I found the answer to what I was trying to find at??http://incolumitas.com/2014/10/19/using-the-python-cryptography-module-with-custom-passwords/ when following up on the URLs.


    In case the site goes off line the code I was after is just (copied from the site) by Nikolai Tschacher:
    import base64
    from cryptography.fernet import Fernet
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.backends import default_backend


    def get_key(password):
    ? ? digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
    ? ? digest.update(password)
    ? ? return base64.urlsafe_b64encode(digest.finalize())


    def encrypt(password, token):
    ? ? f = Fernet(get_key(key))
    ? ? return f.encrypt(bytes(token))


    def decrypt(password, token):
    ? ? f = Fernet(get_key(password))
    ? ? return f.decrypt(bytes(token))


    but the problem I have with this is using a non-randomized password helps subvert the security of the 32-bit random password that Fernet provides. However, as Nikolai notes, it's more usable for interactive activities.


    For new code I'll be using Fernet but for existing code I think I'm forced to keep to PyCrypto. Since a Fernet message is a self-signed (a little like a PKCS12 type file) it will not be appropriate for many existing processes but I think it should be used where possible.?


    Thanks for the help,


    David
    _______________________________________________
    Cryptography-dev mailing list
    Cryptography-dev at python.org
    https://mail.python.org/mailman/listinfo/cryptography-dev
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20150105/f7aaf9c1/attachment.html>

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcryptography-dev @
categoriespython
postedJan 2, '15 at 11:13p
activeJan 5, '15 at 6:26p
posts4
users2
websitepython.org

2 users in discussion

Paul Kehrer: 2 posts David Evans: 2 posts

People

Translate

site design / logo © 2017 Grokbase