LoginSignup
26
38

More than 5 years have passed since last update.

PythonでAES暗号化/復号

Posted at

概要

pythonでのAES暗号化。
前述のphpとnodejsのAES暗号化記事でのソースと相互変換も可能です。
PHPとNode.jsの暗号/復号相互変換

なおソースは下記ページの内容を大幅に参考にしています。ありがとうございます。
Pythonで暗号化と復号化

上記との違いですが、こちらではsaltを毎回生成するため暗号化されたテキストは生成のたび変わるようになっています。

パッケージインストール

$ pip install pycrypto

ソース

crypt.py
import base64
import random
from Crypto.Cipher import AES
from hashlib import sha256

class AESCipher(object):
    def __init__(self, key, block_size=32):
        self.bs = block_size
        if len(key) >= len(str(block_size)):
            self.key = key[:block_size]
        else:
            self.key = self._pad(key)

    def generate_salt(self,digit_num):
        DIGITS_AND_ALPHABETS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        return "".join(random.sample(DIGITS_AND_ALPHABETS, digit_num)).encode()

    def encrypt(self, raw):
        raw = self._pad(raw)
        salt = self.generate_salt(AES.block_size)
        salted = ''.encode()
        dx = ''.encode()
        while len(salted) < 48:
            hash = dx + self.key.encode() + salt
            dx = sha256(hash).digest()
            salted = salted + dx

        key = salted[0:32]
        iv = salted[32:48]

        cipher = AES.new(key, AES.MODE_CBC, iv)
        return base64.b64encode(salt + cipher.encrypt(raw))

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        salt = enc[0:16]
        ct = enc[16:]
        rounds = 3

        data00 = self.key.encode() + salt
        hash = {}
        hash[0] = sha256(data00).digest()
        result = hash[0]
        for i in range(1, rounds):
            hash[i] = sha256(hash[i - 1] + data00).digest()
            result += hash[i]

        key = result[0:32]
        iv = result[32:48]
        cipher = AES.new(key, AES.MODE_CBC, iv)
        return cipher.decrypt(enc[16:]).decode()

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)

    def _unpad(self, s):
        return s[:-ord(s[len(s)-1:])]
make.py
from crypt import AESCipher

# 32文字のパスフレーズ(ランダムキー)
pass_phrase = 'WCWYmSP9eR9nhRidXBDCjMMfUsVfb4Ec'

cipher = AESCipher(pass_phrase)

# 暗号化
encryptText = cipher.encrypt('plain text')
print(encryptText)

#復号
plainText = cipher.decrypt(encryptText)
print(plainText)
26
38
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
38