【Cryptography】Pythonでデータを暗号化する

データを暗号化するときにはPythonのライブラリであるCryptographyを使います。

基本的に企業で扱うデータはすべて暗号化してファイルで管理するとベターです。

平文で持っていると漏洩したときに中身が見られてしまうので情報漏洩になりますが、暗号化しておけば漏洩しても問題はほとんどないといえるでしょう。

最近ではPythonによってディープラーニングやデータ分析のライブラリが豊富に提供されていますが、そのときに使うデータのセキュリティは見落としがちです。

今日はPythonを使って、シンプルに暗号化・複合する方法を紹介します。

[toc]

事前準備

まず使用するデータを用意します。

データ分析でよく用いられるPandasのデータフレームを暗号化対象として使うことにします。

以下のデータは、銀行のお金をやりとりしたデータです。

いつ、だれが、金額などが記載されており、機密情報にあたります。

以下のコマンドで、データフレームをCSVに書き出します。この平文ファイルを暗号化していきたいと思います。

df.to_csv('bank_transfer.csv', index=False)

 

cryptographyというパッケージを使います。

Google colabには入っていませんでしたので以下のコマンドでインストールします。

!pip install cryptography

 

鍵の生成

インストールが終わったら、鍵を作っていきます。

鍵は生成したあとにファイルに保存しておきます。

import cryptography

from cryptography.fernet import Fernet

key = Fernet.generate_key()

print(key)

 

出力は以下の通り。

b'AvEaGfujuN1807pn3gB_CKdkqyJsu69BOfEgs08gASk='

 

最初のbはバイト列であることを示しています。

鍵ファイルや暗号化ファイルはバイト列として扱うので注意しましょう。

文字列(string)ではありません。

ちなみにこのコードは実行するたびに違う鍵が生成されます。

鍵は以下のコードでファイルとして保存します。

ファイルのオプションがwrite byteやread byteになっているので注意です。

with open('key.key', 'wb') as file: #wb = write bytes

file.write(key)

 

読みだすときは以下の通り。

with open('key.key', 'rb') as file: # rb = read bytes

key = file.read()

 

パスワードから鍵を生成する方法

鍵は以上の方法から生成してもよいですが、パスワードから鍵を生成する方法もあります。

こちらの方法だと、パスワードごとに一意の鍵が生成できます

逆に同じパスワードであれば何回実行しても同じ鍵が生成されます。

まずは以下のコマンドでソルトと呼ばれる乱数を作ります。

ソルトは一般的に乱数ですが、できるだけ偏らない乱数のほうが良いです。

偏りが全くない乱数は真正乱数と言われますが、それは作り出すのが難しいといわれています。

OSの乱数生成機能を使って、16桁の乱数を生成します。

import os

os.urandom(16)

 

KDF(Key Derivation Function)という機能を使います。

この引数にはパスワードと先ほど生成したソルトを指定します。

import base64
import os
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

password_provided = 'password'

password = password_provided.encode()

salt = b'\x0b\x05\xean\x83\x0by\xc6\xf7rX\xc9\x10\xc6\xf7y'

#(Password Based Key Derivation Function 2)を使って、パスワードから鍵を生成する
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),

length=32,

salt=salt,

iterations=100000,

backend=default_backend())

key = base64.urlsafe_b64encode(kdf.derive(password))

 

暗号化

鍵が生成できたところで、暗号化、複合をしていきます。

まずは、平文と鍵をファイルから読み込んで、暗号化します。

暗号化したデータはファイルとして出力するようにします。

出力はバイト列になりますので、ファイル名や拡張子は何でもよいです。

# Get the key from the file

with open('key.key', 'rb') as file:

key = file.read()

# Open the file to encrypt

with open('bank_transfer.csv', 'rb') as f:

data = f.read()

fernet = Fernet(key)

encrypted = fernet.encrypt(data)

# Write the encrypted file

with open('bank_transfer.csv.encrypted', 'wb') as f:

f.write(encrypted)

 

出力されるデータは以下のようなバイト列になります。

そのままでは開けないので、メモ帳にドラッグするか、読み込んでGoogle Colab(もしくはJupyter Notebook)で中身を出力するとよいです。

以下はGoogle Colabでの出力結果です。

これで暗号化できましたね!

複合

複合は暗号化の逆の流れです。

暗号化するファイルと鍵を読み込み、複合して平文をファイルとして出力します。

注意点としては、複合したファイル名をcsvの拡張子にしないと開けません。

# Get the key from the file

with open('key.key', 'rb') as file:

key = file.read()

# Open the file to decrypt

with open('bank_transfer.csv.encrypted', 'rb') as f:

data = f.read()

fernet = Fernet(key)

encrypted = fernet.decrypt(data)

# Write the decrypted file

with open('bank_transfer_decrypted.csv', 'wb') as f:

f.write(encrypted)

 

おわり。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog