Oleh Lane Wagner — @wagslane di Twitter

Perlu mengenkripsi beberapa teks dengan kata sandi atau kunci pribadi dengan Python? Anda datang ke tempat yang tepat. AES-256 adalah sandi simetris padat yang biasa digunakan untuk mengenkripsi data untuk diri sendiri. Dengan kata lain, orang yang sama yang mengenkripsi data biasanya juga mendekripsinya (pikirkan manajer kata sandi)

Ketergantungan

Untuk tutorial ini, kita akan menggunakan Python 3. Pastikan Anda menginstal pycrypto, yang akan memberi kita akses ke implementasi AES-256:

pip install pycrypto

Lapisan

AES-256 mengharuskan data yang akan dienkripsi disediakan dalam blok 16-byte. Kami secara naif akan menambahkan spasi di akhir teks tersandi kami untuk memenuhi persyaratan tersebut:

# pad with spaces at the end of the text
# beacuse AES needs 16 byte blocks
def pad(s):
    block_size = 16
    remainder = len(s) % block_size
    padding_needed = block_size - remainder
    return s + padding_needed * ' '

Kita juga akan membuat fungsi unpad() yang menghapus spasi tambahan setelah dekripsi:

# remove the extra spaces at the end
def unpad(s): 
    return s.rstrip()

Mengenkripsi

Sekarang kita membuat fungsi enkripsi(plain_text, password) sederhana. Fungsi ini menggunakan kata sandi untuk mengenkripsi teks biasa. Siapa pun yang memiliki akses ke teks terenkripsi dan kata sandi akan dapat mendekripsinya.

def encrypt(plain_text, password):
    # generate a random salt
    salt = os.urandom(AES.block_size)

    # generate a random iv
    iv = Random.new().read(AES.block_size)

    # use the Scrypt KDF to get a private key from the password
    private_key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # pad text with spaces to be valid for AES CBC mode
    padded_text = pad(plain_text)
    
    # create cipher config
    cipher_config = AES.new(private_key, AES.MODE_CBC, iv)

    # return a dictionary with the encrypted text
    return {
        'cipher_text': base64.b64encode(cipher_config.encrypt(padded_text)),
        'salt': base64.b64encode(salt),
        'iv': base64.b64encode(iv)
    }

Catatan tentang fungsi enkripsi()

  1. IV: Vektor inisialisasi. Vektor inisialisasi harus acak dan baru setiap kali fungsi enkripsi kita digunakan. Anggap saja sebagai garam acak untuk sebuah sandi.
  2. Scrypt: Scrypt digunakan untuk menghasilkan kunci pribadi yang aman dari kata sandi. Hal ini akan mempersulit penyerang untuk melakukan brute force pada enkripsi kami.
  3. Garam: Garam acak baru digunakan untuk setiap proses enkripsi kami. Hal ini membuat penyerang tidak mungkin menggunakan hash yang telah dihitung sebelumnya dalam upaya memecahkan sandi. (lihat meja pelangi)
  4. Scrypt parameter:
  5. N adalah faktor biaya. Ini harus berupa pangkat dua, dan semakin tinggi maka semakin aman kuncinya, namun semakin banyak sumber daya yang dibutuhkan untuk menjalankannya.
  6. R adalah ukuran blok.
  7. P adalah faktor paralelisasi, berguna untuk berjalan pada banyak inti.
  8. Base64: Kami mengkodekan semua data tipe byte kami ke base64 untuk representasi string yang nyaman

Mendekripsi

def decrypt(enc_dict, password):
    # decode the dictionary entries from base64
    salt = base64.b64decode(enc_dict['salt'])
    enc = base64.b64decode(enc_dict['cipher_text'])
    iv = base64.b64decode(enc_dict['iv'])

    # generate the private key from the password and salt
    private_key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # create the cipher config
    cipher = AES.new(private_key, AES.MODE_CBC, iv)

    # decrypt the cipher text
    decrypted = cipher.decrypt(enc)

    # unpad the text to remove the added spaces
    original = unpad(decrypted)

    return original

Catatan tentang fungsi decrypt()

  1. Fungsi decrypt() memerlukan salt dan iv yang sama dengan yang digunakan untuk enkripsi. Kami menggunakan kamus untuk memudahkan penguraian, tetapi jika kami menginginkan satu string teks tersandi, kami dapat menggunakan skema seperti salt.iv.cipher_text
  2. Parameter konfigurasi pada fungsi Scrypt dan AES harus sama dengan fungsi enkripsi.

Beri Saya Kode Lengkapnya!

Anda mungkin ingin melihat semuanya berfungsi dalam contoh skrip. Tidak perlu mencari lagi!

# AES 256 encryption/decryption using pycrypto library
 
import base64
import hashlib
from Crypto.Cipher import AES
from Crypto import Random
import os


# pad with spaces at the end of the text
# beacuse AES needs 16 byte blocks
def pad(s):
    block_size = 16
    remainder = len(s) % block_size
    padding_needed = block_size - remainder
    return s + padding_needed * ' '

# remove the extra spaces at the end
def unpad(s): 
    return s.rstrip()
 
def encrypt(plain_text, password):
    # generate a random salt
    salt = os.urandom(AES.block_size)

    # generate a random iv
    iv = Random.new().read(AES.block_size)

    # use the Scrypt KDF to get a private key from the password
    private_key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # pad text with spaces to be valid for AES CBC mode
    padded_text = pad(plain_text)
    
    # create cipher config
    cipher_config = AES.new(private_key, AES.MODE_CBC, iv)

    # return a dictionary with the encrypted text
    return {
        'cipher_text': base64.b64encode(cipher_config.encrypt(padded_text)),
        'salt': base64.b64encode(salt),
        'iv': base64.b64encode(iv)
    }
 
 
def decrypt(enc_dict, password):
    # decode the dictionary entries from base64
    salt = base64.b64decode(enc_dict['salt'])
    enc = base64.b64decode(enc_dict['cipher_text'])
    iv = base64.b64decode(enc_dict['iv'])

    # generate the private key from the password and salt
    private_key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32)

    # create the cipher config
    cipher = AES.new(private_key, AES.MODE_CBC, iv)

    # decrypt the cipher text
    decrypted = cipher.decrypt(enc)

    # unpad the text to remove the added spaces
    original = unpad(decrypted)

    return original

def main():
    password = input("Password: ")
    
    # First let us encrypt secret message
    encrypted = encrypt("The secretest message", password)
    print(encrypted)
    
    # Let us decrypt using our original password
    decrypted = decrypt(encrypted, password)
    print(bytes.decode(decrypted))

Terima kasih sudah membaca

Lane di Twitter: @wagslane

Jalur di Dev.to: wagslane

Unduh Qvault: https://qvault.io

Postingan AES-256 Cipher — Contoh Kriptografi Python muncul pertama kali di Qvault.