Python Security Cryptography
Python Security Cryptography
& Security
José Manuel Ortega | @jmortegac
https://speakerdeck.com/jmortega
Security Conferences
INDEX
1 Introduction to cryptography
>>Ymnx%nx%r~%xjhwjy%rjxxflj3
Hash functions
Calculate the checksum of some data
File integrity checking
Generate passwords
Digital signatures and authentication
MD5
SHA-2(256 and 512 bits)
SHA-3
Hash
functions
https://docs.python.org/2/library/hashlib.html
Hashlib functions
One-way cryptographic hashing
>>03187564433616a654efef944871f1e4
>>bd576c4231b95dd439abd486be45e23d47a2cbb74b5348b3b113cef47463e15a
>>d47b290aa260af8871294e1ad6b473bd48b587593f8dea7b1b5d9271df12ee081
85a13217ae88e95d9bd425f3ada0593f1671004a2b32380039d3c88f685614c
>>8fadab23df7c580915deba5c6f0eb75bd32181f55c547a2b3999db055398095c33f
10b75c823a288e86636797f71b458
MD5 hash function
Checking file integrity
>>d41d8cd98f00b204e9800998ecf8427e
Hash passwords in DB
Websites store hash of a password
hashlib.sha256(‘password').hexdigest()
>>'5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'
Hash passwords in DB
Hash identifier
https://code.google.com/p/hash-identifier
>>>
d1a2ea7f9661fae8b46b3904b0193ab81516653f73216dfeb5f51afde3d405b2
a secret message
Generating key from password
PyCrypto PBKDF
import Crypto.Random
from Crypto.Protocol.KDF import PBKDF2
PyCrypto RSA
from Crypto.PublicKey import RSA
def generate_RSA(bits=1024):
#Generate an RSA keypair with an exponent of 65537 in PEM format
#param: bits The key length in bits
#Return secret key and public key
new_key = RSA.generate(bits, e=65537)
public_key = new_key.publickey().exportKey("PEM")
secret_key = new_key.exportKey("PEM")
return secret_key, public_key
Generate an RSA secret and public key pair
PyCrypto RSA
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYS9ITbjKu5i9i36FgzKg/HO3o
6CKGJ1c5E57qVlmYF6L1BcgH+eE+XiwJ6fWyShaVnZDuvUapWgQeOGZ60QBJ/vpu
DdwqsuGoTeJNqaRT9ButJa+o+0tchRKBcM6zKUXYWc7kdAlxEpO2OXZEqxD7bd1O
oxv7mEjqBpVXgNEVrwIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCYS9ITbjKu5i9i36FgzKg/HO3o6CKGJ1c5E57qVlmYF6L1BcgH
+eE+XiwJ6fWyShaVnZDuvUapWgQeOGZ60QBJ/vpuDdwqsuGoTeJNqaRT9ButJa+o
+0tchRKBcM6zKUXYWc7kdAlxEpO2OXZEqxD7bd1Ooxv7mEjqBpVXgNEVrwIDAQAB
AoGAc0qqzTTWP5tYciRTmeE02RqAbJoXULHFkRruaf5WsxHptk3bIVakkr9d3V91
NbRqpnby+hjlvly701jlE8LW0QIccII9oWyV6kMSTEJMth9RlXpCbQY285pwg+bF
zyEhQJmjMj1hMDJLQ8dXLCeqXZ37etYGHTT2XQ+q5TOW4YkCQQC5WDQHBhYa/Mzt
UlXemLxv1ERaxt8zmXSX0bKjIkaYMv1SF3FskiN9Rm/zXvil3HuiySBq9g6/fPbN
T1+dtiZTAkEA0lpsRUqamIbii18aBBQGs/FbrUa71ahpoU7+8wXMxNYQBfVGvlzs
J+tKxSecMO196Hl4l5I14ASEs+4wKK5vtQJARe4gmzHRr1cIntY87eKk3nCxZaq5
Vkek9Q86nlB1YEGE0K9lrTgqSb8EyEdh+3qH73CBWboC8H7ew7IZ+nBaXwJBAJEO
K8Vomcz+jvB/B0iyqqChmo+VzGecuCK1f9gEMt21o90H893H5E3u0mO8WdffnciX
I1KaT66ITx5o7SrQh1UCQGqP8B9bpzXjxMuLUJuL1DoRP4QBGHoXokdu8gKAlPzp
ZK8BKRSPRobwlNFlXWfXLAWIFwXIeqOblI20U/oNwNE=
-----END RSA PRIVATE KEY-----
PyCrypto RSA
from Crypto.PublicKey import RSA
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import PKCS1_OAEP
from base64 import b64decode
def encrypt_RSA(public_key, message):
def decrypt_RSA(secret_key, message):
key = (public_key, "r").read()
key = (secret_key, "r").read()
rsakey = RSA.importKey(key)
rsakey = RSA.importKey(key)
rsakey = PKCS1_OAEP.new(rsakey)
rsakey = PKCS1_OAEP.new(rsakey)
encrypted = rsakey.encrypt(message)
decrypted =
return encrypted.encode('base64') rsakey.decrypt(b64decode(message))
return decrypted
PyCrypto Sign/verify
from Crypto.PublicKey import RSA
from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5
from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256
from Crypto.Hash import SHA256 from base64 import b64decode
from base64 import b64encode, b64decode
def verify_sign(public_key, signature, data): ‘
def sign_data(secret_key, data): #Verifies with a public key that the data was signed by their
key = (secret_key, "r").read() #private key
rsakey = RSA.importKey(key) pub_key = (public_key, "r").read()
signer = PKCS1_v1_5.new(rsakey) rsakey = RSA.importKey(pub_key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest = SHA256.new()
digest.update(b64decode(data)) digest.update(b64decode(data))
sign = signer.sign(digest) if signer.verify(digest, b64decode(signature)):
return b64encode(sign) return True
return False
PyCrypto RSA/Sign/verify
True
True
True
public_key
<_RSAobj @0x2b56648 n(1024),e>
encrypted data
('I\xe6\xff\\
M$\x12\xbb\x95\xee\x02\xcf\x82Im\tf+\x1f\xaeU\xbdv`
^\x94\xfa\xe6_\x8b\xed\x8d\xa3\xab\xfc
\xae\x17\x07=|\x18\xca\x18j\xc5\x1d\x01\xad`\xd6W
E\xfbU\xd1\x12\x0c-
\xb6\x9c\xc4\x07\xaa\x93<\xb5zw&\x98\xa2\xdc\x8e\
x9e-
\x06gQ\xcf\xfa\xc8r/\xd5\x98|\xd5\xcdg\xb2\xda\xcd:
d\xaf\xde\xe2\xcd\xcd\xf5{p`\x07\xbb~\x1b\xa4hHJ#c\
tE6\xfa\xc3\x87\x8d\xf2O8,\xe2W',)
signature
(445755122549853282247622461459180943435051515
5918916324891286777775175591376873419505852842
3900156177220742858645089371096255086061177099
8101038368420840785203067622854793789417670298
3088451295738677105320376959152029164761636442
8930467543317371804318093617486393498897888949
152557196686676342045445446511829L,)
decrypt_data EUROPHYTON2015
True
Best practices
Avoid hashing methods like MD5 or SHA-1,use at
least SHA-2 or SHA-3
Key Stretching for strong passwords
Preventing Brute-force or dictionary attacks
for i in xrange(iterations):
m = hashlib.sha512()
m.update(key + password + salt)
key = m.digest()
https://cryptography.io
Cryptography
$ pip install cryptography
Django-secure package
Django Security
https://www.securedjango.com
Password storage
class PBKDF2PasswordHasher(BasePasswordHasher):
"""
Secure password hashing using the PBKDF2 algorithm (recommended)
Configured to use PBKDF2 + HMAC + SHA256.
The result is a 64 byte binary string. Iterations may be changed
safely but you must rename the algorithm if you change SHA256.
"""
algorithm = "pbkdf2_sha256"
iterations = 24000
digest = hashlib.sha256
def select_user(request):
user = request.GET['username']
sql = "SELECT * FROM users WHERE username = %s"
cursor = connection.cursor()
cursor.execute(sql, [user])
SQL injection
Django ORM –QuerySets -Models
Django automatically gives you a database-abstraction API that lets
you create, retrieve, update and delete objects
Write python classes and it will convert to SQL securely
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
def render_page(request):
user = request.GET['username']
return render(request, ‘page.html', {‘user’: user})
Security best practices in forms
Validate form data with Django Forms package
Use POST method in HTML Forms
Use Meta.Fields in ModelForms
Steganography
Hiding data(text/images) within images