3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AES暗号化をPythonとJavascriptでやってみる話(備忘録)

Last updated at Posted at 2024-01-30

この記事の大まかな内容

PythonのFlaskを使用してWEBアプリ開発をしていたのだが、ローカル環境で動かす専門のWEBアプリのため、SSL証明書が取得できないし、
OpenSSLを使用してもいいが、chromeブラウザくんは警告を出しまくるし、何より、常に危険マークがつくのは気に食わないということでせめてAES暗号化をして通信をしてあげたいと思ったわけです。

注意点

  • 個人の備忘録なので、あまり参考にならないと思います。
  • この記事がきっかけになるいかなる損害も責任を負いません
  • セキュリティ上危険と言われる可能性があるので、公式のドキュメントを参照してください
  • WebCryptoAPIを最初使っていましたが、非SSL時に使用できないです!

PythonでAESキーを作成する

今回私のプロジェクトではPythonをサーバーで動かして処理をしているので、AESキーとIVをサーバーで作成します。
今回はFlaskのプロジェクトなのでapp.configに保存しました。
今回は、cryptographyライブラリを使用しますので、pipダウンロードしておきます。

必要なライブラリのインポート

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

AES鍵の作成

def generate_AES_key():
    key = os.urandom(32)
    iv = os.urandom(16)
    return key, iv
app.config["AES_KEY"], app.config["AES_IV"] = generate_AES_key()

PythonでAESを使用して暗号化&復号する

暗号化

def Encrypt(aes_key, aes_iv, encrypt_text):
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(encrypt_text.encode()) + padder.finalize()
    cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend())
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()
    return ciphertext

復号

def Decryption(aes_key, aes_iv, decrypt_text):
    cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend())
    decryptor = cipher.decryptor()
    padded_data = decryptor.update(decrypt_text) + decryptor.finalize()
    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    plaintext = unpadder.update(padded_data) + unpadder.finalize()
    return plaintext.decode()

Javascriptで暗号化&復号する

暗号化

※非同期関数で実行
まずは、CDNを使用してライブラリを読み込む

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
const key = CryptoJS.enc.Base64.parse(responseData['aes_key']);
const iv = CryptoJS.enc.Base64.parse(responseData['aes_iv']);

const ciphertext = CryptoJS.AES.encrypt(data, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
return ciphertext.toString()

復号

const key = CryptoJS.enc.Base64.parse(responseData['aes_key']);
const iv = CryptoJS.enc.Base64.parse(responseData['aes_iv']);
const decrypted = CryptoJS.AES.decrypt(data, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
const plaintext = decrypted.toString(CryptoJS.enc.Utf8);
return plaintext

おわり

これ以上話すことはないし、正直言ってあまり良くない というか最悪だから、ちゃんと使うときは、皆さん正しく書きましょうね。。。
ここでは、AESキーの交換を裸の状態でやっているので最初の鍵交のときには、クライアント側で公開鍵暗号方式の公開鍵をサーバーに送りつけて、サーバー側でAES鍵をクライアント公開鍵で暗号化して、クライアント側に送り返して、クライアント側で秘密鍵を使用して、複合するような形で、AES鍵の交換をするのがいいと思います。

多分もっとほかのやりかたもあるとは思いますが

3
2
0

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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?