Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YannBouyeron/c5367809904a682767669b6a51f03aa3 to your computer and use it in GitHub Desktop.
Save YannBouyeron/c5367809904a682767669b6a51f03aa3 to your computer and use it in GitHub Desktop.
Chiffrement asymétrique (RSA) et symétrique (AES) avec PyCryptodome et Fernet

Chiffrement asymétrique (RSA) et symétrique (AES) avec PyCryptodome et Fernet

Installer les modules nécessaires

pip install pycryptodome

pip install cryptography

RSA: Encrypt / Decrypt

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

key = RSA.generate(2048)

pub = PKCS1_OAEP.new(key.publickey())

priv = PKCS1_OAEP.new(key)

encrypted_message = pub.encrypt(b"salut")

decrypted_message = priv.decrypt(encrypted_message)

RSA: Signe / Verify

from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA

key = RSA.generate(2048)

# sign

message = b"mon message à signer"

h = SHA256.new(message)

signature = pkcs1_15.new(key).sign(h)

# verify

h = SHA256.new(message)

try:

    pkcs1_15.new(key.publickey()).verify(h, signature)
    print("La signature est valide")

except(ValueError,TypeError):

	print("La signature est invalide.")                                                                                                                               

RSA: Export / Import Keys

from Crypto.PublicKey import RSA

key = RSA.generate(2048)

private_key = key.export_key()

file_out = open("private.pem", "wb")
file_out.write(private_key)
file_out.close()

public_key = key.publickey().export_key()

file_out = open("public.pem", "wb")
file_out.write(public_key)
file_out.close()

priv = RSA.import_key(open("private.pem").read())
pub = RSA.import_key(open("public.pem").read())

AES create 32 bytes key

Avec pycryptodome:

from Crypto.Random import get_random_bytes
import base64

key = get_random_bytes(32)

key = base64.urlsafe_b64encode(key) # return 44 bytes key uniquement pour Fernet

key = key[:32] # pycryptodome AES necessite une 32 bytes key 

Avec Fernet:

from cryptography.fernet import Fernet

key = Fernet.generate_key() # return 44 bytes key uniquement pour Fernet

Par dérivation d’un mot de passe avec PBKDF2:

from Crypto.Protocol.KDF import PBKDF2
from Crypto import Random
import base64

pwd = "my_secret_password"

salt = Random.new().read(8)

key = PBKDF2(pwd, salt, 32)
	
key = base64.urlsafe_b64encode(key) # return 44 bytes key uniquement pour Fernet

key = key[:32] # pycryptodome AES necessite une 32 bytes key 

Avec secrets:

import secrets
import base64

key = secrets.token_bytes(32)

key = base64.urlsafe_b64encode(key) # return 44 bytes key uniquement pour Fernet

key = key[:32] # pycryptodome AES necessite une 32 bytes key 

AES Fernet: Encrypt / Decrypt

from cryptography.fernet import Fernet

key = Fernet.generate_key() 

f = Fernet(key)

m = "message à chiffrer"

e = f.encrypt(m.encode())

d = f.decrypt(e)

d = d.decode()

AES Fernet: Derive key from password & Encrypt / Decrypt

from Crypto.Protocol.KDF import PBKDF2
from cryptography.fernet import Fernet
from Crypto import Random
import base64


salt = Random.new().read(8)


def encrypt(pwd, msg):

	"""
	param pwd: password or passphrase (type: str)
	param msg: message to encrypt (type: str or bytes) 
	
	return base64 encoded encrypted message
	"""
	
	try:
		msg = msg.encode()
	
	except:
		pass
	
	key = PBKDF2(pwd, salt, 32)
	
	key = base64.urlsafe_b64encode(key)
	
	f = Fernet(key)
	
	e = f.encrypt(msg)

	return base64.b64encode(e)
	
def decrypt(pwd, msg):
	
	"""
	param pwd: password or passphrase (type: str)
	param msg: message to uncrypt (type: bytes) 
	
	return uncrypted decoded message (str)
	"""
	
	msg = base64.b64decode(msg)
	
	key = PBKDF2(pwd, salt, 32)
	
	key = base64.urlsafe_b64encode(key)
	
	f = Fernet(key)
	
	d = f.decrypt(msg)
	
	return d.decode()

AES Crypto: Derive key from password & Encrypt / Decrypt

from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
import base64


salt = Random.new().read(8)


def encrypt(pwd, msg):

	"""
	param pwd: password or passphrase (type: str)
	param msg: message to encrypt (type: str or bytes) 
	
	return base64 encoded encrypted message
	"""
	

    try:
        msg = msg.encode()

    except:
        pass

    key = PBKDF2(pwd, salt, 32)

    key = base64.urlsafe_b64encode(key)

    cipher = AES.new(key[:32], AES.MODE_EAX)

    nonce = cipher.nonce

    e, tag = cipher.encrypt_and_digest(msg)

    r = tag + nonce + e

    return base64.b64encode(r)
    
    
def decrypt(pwd, msg):

	"""
	param pwd: password or passphrase (type: str)
	param msg: message to uncrypt (type: bytes) 
	
	return uncrypted decoded message (str)
	"""
	

    msg = base64.b64decode(msg)

    tag = msg[:16]

    nonce = msg[16:32]

    e = msg[32:]


    key = PBKDF2(pwd, salt, 32)

    key = base64.urlsafe_b64encode(key)
    
    cipher = AES.new(key[:32], AES.MODE_EAX, nonce=nonce)

    d = cipher.decrypt(e)

    try:
        cipher.verify(tag)
        
        return d.decode()

    except ValueError:

        return ""

Salsa20: Derive key from password & Encrypt / Decrypt

Contrairement à AES qui est une méthode de chiffrement symétrique par blocs, Salsa20 permet de réaliser un chiffrement symétrique par flot (ou chiffrement par flux).

from Crypto.Cipher import Salsa20
from Crypto.Protocol.KDF import PBKDF2
import base64


salt = Random.new().read(8)


def encrypt(pwd, msg):

	"""
	param pwd: password or passphrase (type: str)
	param msg: message to encrypt (type: str or bytes) 
	
	return base64 encoded encrypted message
	"""
	

    try:
        msg = msg.encode()
    
    except:
        pass

    key = PBKDF2(pwd, salt, 32)
    
    key = base64.urlsafe_b64encode(key)

    key = key[:32]
   
    cipher = Salsa20.new(key=key)
    
    e = cipher.nonce + cipher.encrypt(msg)

    return base64.b64encode(e)
    

def decrypt(pwd, msg):

	"""
	param pwd: password or passphrase (type: str)
	param msg: message to uncrypt (type: bytes) 
	
	return uncrypted decoded message (str)
	"""
	
   
    if len(msg) > 0:

        msg = base64.b64decode(msg)
        
        key = PBKDF2(pwd, salt, 32)
    
        key = base64.urlsafe_b64encode(key)

        key = key[:32]
    
        msg_nonce = msg[:8]
    
        ciphertext = msg[8:]
    
        cipher = Salsa20.new(key=key, nonce=msg_nonce)
    
        d = cipher.decrypt(ciphertext)

        return d.decode()
    
    else:

        return ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment