Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cooking with Cryptography - PyCon Australia 2015

Cooking with Cryptography - PyCon Australia 2015

Talk about python-cryptography library (https://cryptography.io).

Video: https://www.youtube.com/watch?v=c16jwvOmKxM

Fraser Tweedale

August 01, 2015
Tweet

More Decks by Fraser Tweedale

Other Decks in Programming

Transcript

  1. Admonition Do not invent your own crypto primitives Do not

    write your own crypto implementations Do not use low-level crypto unless you know you have to Use the right primitive for the job, and use it right
  2. Background Existing libraries: M2Crypto, PyCrypto, PyOpenSSL Lagging in Python 3,

    PyPy support Insecure implementations, bad APIs, poor defaults Missing some modern primitives, cipher modes Lack of high-level APIs for common use cases GIL issues
  3. Enter Cryptography Started by Alex Gaynor in July 2013 Python

    Cryptographic Authority (PyCA) formed Oct 2013 Custodian of several crypto libs including Cryptography Supports Python 2.6, 2.7, 3.3+ and PyPy
  4. Goal To be Python’s cryptographic standard library Provide high-level human-friendly

    APIs for common use cases “Batteries included” c.f. NaCl (http://nacl.cr.yp.to/) Stable API
  5. Fernet - encryption from cryptography.fernet import Fernet message = b"for

    your eyes only" # 32-byte base64url-encoded string key = Fernet.generate_key() f = Fernet(key) # base64url-encoded token token = f.encrypt(message)
  6. Fernet - decryption # key storage/distribution is out of scope

    f = Fernet(key) try: message = f.decrypt(ciphertext) except cryptography.fernet.InvalidToken: print "decryption failed"
  7. X.509 The prevailing PKI for Internet Certificates and CRLs (RFC

    5280) Certificate requests (PKCS #10, RFC 2986) Supports common extensions
  8. X.509 - certificate request from cryptography import x509 cn =

    x509.NameAttribute(x509.OID_COMMON_NAME, u’foo.com’) alt_name = x509.DNSName(u’www.foo.com’) builder = x509.CertificateSigningRequestBuilder() \ .subject_name(x509.Name([cn])) \ .add_extension(x509.SubjectAlternativeName([alt_name]) csr = builder.sign( private_key, hashes.SHA256(), default_backend())
  9. Primitives Digests: SHA-1, SHA-2, . . . MACs: HMAC One-time

    pads: HOTP, TOTP Key-stretching: PBKDF2, HKDF Block ciphers: AES, 3DES, . . . Public-key algorithms: DSA, RSA, ECDSA, DH Serialisation: DER, PEM, OpenSSH
  10. Backends Implementations of primitives are provided by backends Backends implement

    interfaces CipherBackend, HashBackend, . . . Backends available: OpenSSL, CommonCrypto (OS X, iOS) Use MultiBackend to compose backends
  11. FreeIPA Vault User self-service secret store Key escrow Symmetric or

    asymmetric encryption http://www.freeipa.org/
  12. FreeIPA Vault def encrypt(self, data, symmetric_key=None, public_key=None): if symmetric_key: return

    Fernet(symmetric_key).encrypt(data) elif public_key: return public_key.encrypt( data, padding.PKCS1v15())
  13. FreeIPA Vault def decrypt(self, data, symmetric_key=None, private_key=None): try: if symmetric_key:

    return Fernet(symmetric_key).decrypt(data) elif private_key: return private_key.decrypt( data, padding.PKCS1v15()) except (InvalidToken, ValueError): raise errors.AuthenticationError( message=_(’Invalid credentials’))
  14. jwcrypto - imports from cryptography.hazmat.primitives.asymmetric \ import padding, rsa from

    cryptography.hazmat.primitives import hashes padfn = padding.PKCS1v15() hashfn = hashes.SHA256()
  15. jwcrypto - read private key def _rsa_pri(jwk): return rsa.RSAPrivateNumbers( _decode_int(jwk[’p’]),

    _decode_int(jwk[’q’]), _decode_int(jwk[’d’]), _decode_int(jwk[’dp’]), _decode_int(jwk[’dq’]), _decode_int(jwk[’qi’]), _rsa_pub(jwk) )
  16. jwcrypto - sign def sign(jwk, payload): private_key = _rsa_pri(jwk) #

    get an AsymmetricSignatureContext signer = private_key.signer(padfn, hashfn) signer.update(payload) signature = signer.finalize() return signature
  17. jwcrypto - verify def verify(jwk, payload, signature): public_key = _rsa_pub(jwk)

    # get an AsymmetricVerificationContext verifier = \ public_key.verifier(signature, padfn, hashfn) verifier.update(payload) try: verifier.verify() except cryptography.exception.InvalidSignature: # ruh roh
  18. Security No memory wiping Has not been formally audited OpenSSL

    statically linked on Windows Use os.urandom for randomness
  19. Conclusion Avoid low-level crypto where possible Cryptography has: high-level APIs

    for common use cases most of the primitives you’re ever likely to need Consider making it your crypto standard library If Cryptography doesn’t meet your needs. . . are you doing the right thing? contribute!
  20. Fin Copyright 2015 Red Hat, Inc. This work is licensed

    under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. Slides https://github.com/frasertweedale/talks/ Email [email protected] Twitter @hackuador