🔐

Cryptoで暗号/復号・署名/検証をしてみる

2024/05/11に公開

海洋ロボコンをやってた人です。
今回はCryptoで暗号/復号・著名検証を試してみたので、備忘録として記載しておきます。

以下箇条書きになりますが、何卒宜しくお願い致します。

1: Input

https://www.tohoho-web.com/ex/crypt.html

https://qiita.com/TakahikoKawasaki/items/4c35ac38c52978805c69

https://qiita.com/kj1/items/aebbb73a034f36d73e40


詳細は上記に記載があるので省きますが、自身の理解&アウトプット兼ねて概要を記載します。

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
terminal
pip3 install pycryptodome

https://www.pycryptodome.org/

  • folder
    ・encrypt_signature.py
    ・data.txt
    ・decrypt_verification.py

2.2: Source Code

encrypt_signature.py
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)
data.txt
ros2 topic name: /float32/data

encrypt_signature.pyを実行すると以下のようになり、data.txtが暗号化されているのが確認できます。

また、署名データ、公開鍵、秘密鍵も書き出しているので、これらも確認できます。
署名データはSHAハッシュ+RSA暗号により中身が見れないこともわかります。

decrypt_verification.py
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