【Python暗号化】pycryptoではなくpycryptodomeを使う

【Python暗号化】pycryptoではなくpycryptodomeを使う プログラミング

「Python 暗号化」で調べると、pycryptoが出てきます。
でも、pycryptoはもう古すぎて使えません。
セキュリティ的にもおススメできません。

その代わりに、pycryptodomeを使いましょう。

本記事の内容

  • pycryptodomeとは?
  • pycryptodomeのシステム要件
  • pycryptodomeのインストール
  • pycryptodomeの動作確認

それでは、上記に沿って解説していきます。

pycryptodomeとは?

pycryptodomeは、データの暗号化・復号化を可能にするPythonライブラリです。
ただ、Pythonで暗号化と言えば、pycryptoの方が知名度があります。

知名度と言う点では、pycryptodomeはまだまだでしょう。
しかし、pycryptodomeはpycryptoの後継のようなモノです。

pycryptoは、すでに開発がストップしています。
2013年10月18日にpycrypto 2.6.1をリリースしたのが、最後となります。

そして、そのソースコードをフォークしたのがpycryptodomeです。
その意味では、pycryptodomeがpycryptoの後継ライブラリと言えます。

pycryptoはもう古すぎて、使うのは危険です。
もしかしたら、インストールすらできないかもしれません。

よって、pycryptoではなくpycryptodomeをインストールしましょう。

以上、pycryptodomeについての説明でした。
次は、pycryptodomeのシステム要件を確認します。

pycryptodomeのシステム要件

現時点(2021年7月)での pycryptodomeの最新バージョンは、3.10.1となります。
この最新バージョンは、2021年2月9日にリリースされています。

サポートOSに関しては、以下を含むクロスプラットフォーム対応となります。

  • Windows
  • macOS
  • Linux

基本的には、OSは問わないということです。
そして、サポート対象となるPythonのバージョンは以下。

  • Python 2.7
  • Python 3.5
  • Python 3.6
  • Python 3.7
  • Python 3.8
  • Python 3.9

個人的には、これだけ幅広い対応には反対です。
基本的には、下記のPythonの公式開発サイクルに合わせるだけで十分だと思います。

バージョンリリース日サポート期限
3.62016年12月23日2021年12月
3.72018年6月27日2023年6月
3.82019年10月14日2024年10月
3.92020年10月5日2025年10月

Python 2系と3系の両方をサポートする場合、互換性を保つ分だけコードは膨れ上がるでしょう。
セキュリティ的にも、それはよろしくないと思います。
もちろん、パフォーマンス的にも。

互換性という言葉の響きは、カッコイイです。
それにメリットもあるでしょう。
でも、同時にデメリットもあるということです。

以上、pycryptodomeのシステム要件についての説明でした。
次は、pycryptodomeをインストールしていきます。

pycryptodomeのインストール

最初に、Pythonのバージョンを確認しておきます。

>python -V
Python 3.9.6

次に、現状のインストール済みパッケージを確認しておきます。

>pip list
Package    Version
---------- -------
pip        21.1.3
setuptools 57.0.0

次にするべきことは、pipとsetuptoolsの更新です。
pipコマンドを使う場合、常に以下のコマンドを実行しておきましょう。

python -m pip install --upgrade pip setuptools

では、pycryptodomeのインストールです。
pycryptodomeのインストールは、以下のコマンドとなります。

pip install pycryptodome

インストールは、すぐに終わります。
では、どんなパッケージがインストールされたのかを確認しましょう。

>pip list
Package      Version
------------ -------
pip          21.1.3
pycryptodome 3.10.1
setuptools   57.0.0

依存パッケージは、ゼロです。
その点では、pycryptodomeを容易に導入できます。

加えて、OSはクロスプラットフォーム、Pythonバージョンの制約もほぼナシです。
この対応力を良しとするかどうかという疑問は残りますが。。。
それがどうであれ、開発陣の努力には本当に感謝ですね。

以上、pycryptodomeのインストールについての説明でした。
最後は、pycryptodomeの動作確認を行います。

pycryptodomeの動作確認

pycryptodomeの動作確認は、次の3つの処理に分けられます。

  • 秘密鍵・公開鍵の作成
  • 公開鍵を使ったデータの暗号化
  • 秘密鍵を使ったデータの復号化

それぞれを下記で説明します。

秘密鍵・公開鍵の作成

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()

秘密鍵と公開鍵をセットで作成します。
セットじゃないと意味がないですからね。
利用の場合は、必ずセットで作成された鍵を利用する必要があります。

上記コードを実行すると、次のファイルが作成されます。

  • private.pem(秘密鍵)
  • public.pem(公開鍵)

これらの鍵を使って、暗号化と復号化を検証していきます。

公開鍵を使ったデータの暗号化

一般的には、データの送信者が公開鍵を利用します。
渡された公開鍵を用いて、送りたいデータを暗号化することになります。

このことを実現するのが、次のコードです。

from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP

data = "日本語で書かれた秘密のメッセージ".encode("utf-8")
file_out = open("encrypted_data.txt", "wb")

recipient_key = RSA.import_key(open("public.pem").read())
session_key = get_random_bytes(16)

# セッションキーをRSA公開鍵で暗号化する
cipher_rsa = PKCS1_OAEP.new(recipient_key)
enc_session_key = cipher_rsa.encrypt(session_key)

# データをAESセッションキーで暗号化
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
[file_out.write(x) for x in (enc_session_key, cipher_aes.nonce, tag, ciphertext)]
file_out.close()

公開鍵を使って、データを暗号化しています。
その暗号化されたデータは、encrypted_data.txtというファイルに保存されています。
もちろん、encrypted_data.txtの中身は以下のように暗号化されています。

秘密鍵を使ったデータの復号化

一般的には、データの受信者が秘密鍵を利用します。
渡された秘密鍵を用いて、送りたいデータを復号化することになります。

このことを実現するのが、次のコードです。

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

file_in = open("encrypted_data.txt", "rb")

private_key = RSA.import_key(open("private.pem").read())

enc_session_key, nonce, tag, ciphertext = \
    [file_in.read(x) for x in (private_key.size_in_bytes(), 16, 16, -1)]

# セッションキーをRSA秘密鍵で復号する
cipher_rsa = PKCS1_OAEP.new(private_key)
session_key = cipher_rsa.decrypt(enc_session_key)

# データをAESセッションキーで復号する
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag)
print(data.decode("utf-8"))

秘密鍵を使って、データを復号化しています。
上記のコードを実行すると、復号化されたデータが表示されます。

日本語で書かれた秘密のメッセージ

まとめ

秘密鍵・公開鍵のセットというのが、重要です。
これさえ注意すれば、簡単に暗号化・復号化が実現できます。

以上、pycryptodomeの動作確認について説明しました。

タイトルとURLをコピーしました