Cryptoで暗号/復号・署名/検証をしてみる
海洋ロボコンをやってた人です。
今回はCryptoで暗号/復号・著名検証を試してみたので、備忘録として記載しておきます。
以下箇条書きになりますが、何卒宜しくお願い致します。
1: Input
詳細は上記に記載があるので省きますが、自身の理解&アウトプット兼ねて概要を記載します。
1.1: Encryption/Decryption
・暗号化(Encryption)と復号化(Decryption)は不正アクセスや盗聴からデータを保護するために活用され、情報セキュリティが必要な用途で使用される。
・暗号化を「公開鍵」、復号化を「秘密鍵」とする「公開鍵暗号方式」が使用される。
・復号時は、暗号化データを受け取るユーザーのみが読み取れる必要があるので「秘密鍵」を使って復号をする。
・公開鍵暗号方式の代表例として「RSA(Rivest-Shamir-Adleman)」があり、鍵長は2048bitが一般的に使用される。
・RSA暗号時、平文の前後にパディングを追加し、暗号化するブロックサイズを整数倍に調整する。
・パディングには「PKCS #1 v1.5」、「PSS(Probabilistic signature scheme)」などが使用される
1.2: Sign/Verify
・データが正当なものかどうかを確認するために署名(Sign)を利用し、データ改ざん、なりすましを検出/検証(Verify)するために活用される。
・署名作成を「秘密鍵」、検証を「公開鍵」と使用して署名の正当性を確認する。
・RSA署名作成時、メッセージからハッシュ関数によりハッシュ値を計算し、パディング処理したデータをRSA暗号を行うことで署名を作成する。
・ハッシュ値は不可逆であり、SHA-2規格の「SHA-256(Secure Hash Algorithm 256bit)」などが一般的に使用される。
2: Software
2.1: Setup
- Environment
Ubuntu 22.0
Python 3.10.12
- Installtion
pip3 install pycryptodome
- folder
・encrypt_signature.py
・data.txt
・decrypt_verification.py
2.2: Source Code
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.Cipher import PKCS1_OAEP
# RSAキーペアの生成
def generate_key_pair():
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
return private_key, public_key
# データの署名作成
def sign_data(data, private_key):
key = RSA.import_key(private_key)
h = SHA256.new(data)
signer = PKCS1_v1_5.new(key)
signature = signer.sign(h)
return signature
# データの暗号化
def encrypt_data(data, public_key):
key = RSA.import_key(public_key)
cipher = PKCS1_OAEP.new(key)
encrypted_data = cipher.encrypt(data)
return encrypted_data
# ファイルに書き出す
def write_file(file_path, data):
with open(file_path, 'wb') as file:
file.write(data)
# テスト用ファイルのパス
binary_file_path = "data.txt"
# 鍵の生成
private_key, public_key = generate_key_pair()
# 公開鍵と秘密鍵のファイルへの書き出し
write_file("public_key.pem", public_key)
write_file("private_key.pem", private_key)
# テスト用ファイルの読み込み
with open(binary_file_path, 'rb') as file:
data = file.read()
# データの署名作成
signature = sign_data(data, private_key)
# データの署名をファイルに書き出し
write_file("signature.bin", signature)
# データの暗号化
encrypted_data = encrypt_data(data, public_key)
# 暗号化されたデータと署名をファイルに書き出し
write_file("encrypted_data.txt", encrypted_data)
ros2 topic name: /float32/data
encrypt_signature.pyを実行すると以下のようになり、data.txtが暗号化されているのが確認できます。
また、署名データ、公開鍵、秘密鍵も書き出しているので、これらも確認できます。
署名データはSHAハッシュ+RSA暗号により中身が見れないこともわかります。
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.Cipher import PKCS1_OAEP
# データの署名検証
def verify_signature(data, signature, public_key):
key = RSA.import_key(public_key)
h = SHA256.new(data)
verifier = PKCS1_v1_5.new(key)
if verifier.verify(h, signature):
return True
else:
return False
def read_file(file_path):
with open(file_path, 'rb') as file:
data = file.read()
return data
# データの復号化
def decrypt_data(encrypted_data, private_key):
key = RSA.import_key(private_key)
cipher = PKCS1_OAEP.new(key)
decrypted_data = cipher.decrypt(encrypted_data)
return decrypted_data
input_file = "encrypted_data.txt"
output_file = "decrypted_data.txt"
signature_file_path = "signature.bin"
public_key_file_path = "public_key.pem"
private_key_file_path = "private_key.pem"
combined_data = read_file(input_file)
signature = read_file(signature_file_path)
public_key = read_file(public_key_file_path)
private_key = read_file(private_key_file_path)
# データの復号化
decrypted_data = decrypt_data(combined_data, private_key)
# 復号化されたデータをファイルに書き込む
with open(output_file, 'wb') as file:
file.write(decrypted_data)
output = read_file(output_file)
# データの署名検証
if verify_signature(output, signature, public_key):
print("Signature verification successful.")
else:
print("Signature verification failed.")
decrypt_verification.pyで復号、署名検証して中身のデータを確認してみます。
decryptしたデータが元データと正しいことが確認できますね。
以上です。
Likeいただけると大変励みになりますので、よろしくお願いいたします。
Discussion