本記事よりも、2019-3-2 に書き改めた方を参照すべし。。
oboe2uran.hatenablog.com
先日書いた、
Java と Python 相互で AES 256 暗号/複合を実行する - Oboe吹きプログラマの黙示録
やはり、Python のコードを改める。
複合メソッド、Base64 受け取りとHex文字列受け取りが分かれるより引数で指定することにする。
名称も、どうせ 256 bit 長しか今後も使わないので、cryptoaes256.py でなくて、cryptoaes.py にする。
複合メソッドで渡す形式は文字列型だけにする
# -*- coding: UTF-8 -*- # AES 256 暗合複合 # 使い方: # from cryptoaes import AESCipher # CBCモードインスタンス # aes = AESCipher(password, bytes.fromhex(iv_hex_string)) # ECBモードインスタンス # aes = AESCipher(password) # # CBCモード 暗合化 → Base64 エンコード # enctxt = b64encode(aes.encryptCBC(planetxt)).decode('utf-8') # CBCモード 複合 ← Base64エンコード済の暗号文 # dectxt = aes.decryptCBC(encted_b64_string) # CBCモード 複合 ← 16進 Hex表現 の暗号文 # dectxt = aes.decryptCBC(encted_hexstring, type='hex') # # ECBモード 暗合化 → Base64 エンコード # enctxt = b64encode(aes.encryptECB(planetxt)).decode('utf-8') # ECBモード 複合 ← Base64エンコード済の暗号文 # dectxt = aes.decryptECB(encted_b64_string) # CBCモード 複合 ← 16進 Hex表現 の暗号文 # dectxt = aes.decryptECB(encted_hexstring, type='hex') # import re import hashlib from Crypto.Cipher import AES from Crypto import Random from base64 import b64encode, b64decode BLOCK_SIZE = AES.block_size pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) unpad = lambda s: s[:-ord(s[len(s) - 1:])] class AESCipher: def __init__(self, password, iv=Random.new().read(AES.block_size)): self.key = hashlib.sha256(password.encode("utf-8")).digest() self.iv = iv # AES 256キー参照 def getKey(self): return self.key # ベクトル値取得 def getIV(self): return self.iv # password & ベクトル値セット def setPasswdAndIV(self, passandiv): self.key = hashlib.sha256(passandiv[0].encode("utf-8")).digest() self.iv = passandiv[1] # CBC モード暗号化 plane → byte def encryptCBC(self, message): if message is None or len(message) == 0: raise NameError("No value given to encrypt") raw = b64encode(message.encode('utf-8')).decode() raw = pad(raw) raw = raw.encode('utf-8') cipher = AES.new(self.key, AES.MODE_CBC, self.iv) return cipher.encrypt(raw) # CBC モード複合 encrypted base64 or HEX → plane def decryptCBC(self, enctext, type='b64'): if enctext is None or len(enctext) == 0: raise NameError("No value given to decrypt") cipher = AES.new(self.key, AES.MODE_CBC, self.iv) if type=='b64': return b64decode(cipher.decrypt(b64decode(enctext))).decode() elif type=='hex': re.sub(b"([\x00-\x08\x0b\x0c\x0e-\x1f])*$", b'', cipher.decrypt(bytes.fromhex(enctext))).decode() else: raise TypeError("type Error must be 'b64' or 'hex'") # ECB モード暗号化 plane → byte def encryptECB(self, message): if message is None or len(message) == 0: raise NameError("No value given to encrypt") raw = b64encode(message.encode('utf-8')).decode() raw = pad(raw) raw = raw.encode('utf-8') cipher = AES.new(self.key, AES.MODE_ECB) return cipher.encrypt(raw) # ECB モード複合 encrypted base64 or HEX → plane def decryptECB(self, enctxt, type='b64'): if enctxt is None or len(enctxt) == 0: raise NameError("No value given to decrypt") cipher = AES.new(self.key, AES.MODE_ECB) if type == 'b64': return b64decode(cipher.decrypt(b64decode(enctxt)).decode()).decode() elif type == 'hex': re.sub(b"([\x00-\x08\x0b\x0c\x0e-\x1f])*$", b'', cipher.decrypt(bytes.fromhex(enctext))).decode() else: raise TypeError("type Error must be 'b64' or 'hex'") # password と iv を再セットするための タプルを生成 def createPasswordAndIV(): import random import string return (''.join(random.choices(string.ascii_letters + string.digits, k=16)), Random.new().read(AES.block_size) )
次は、Java の方の見直しだ。