Pythonでのデジタル署名(署名と検証、暗号化と復号化)
■パッケージcryptographyを使ったサンプル。
Androidの配布についてデジタル署名が出てきたので、少しおさらい。Pythonのパッケージcryptographyでデジタル署名が利用できるようなので、署名と検証、暗号化と復号化を見てみる。
サンプルコードが下のもの。
暗号鍵の作成、署名と検証のコード、暗号化と復号化のコードで、適当にprintで結果をコンソール表示している。
import base64
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# ==============================================================
# 暗号鍵(private key)の作成
private_key_sample033 = rsa.generate_private_key(
public_exponent=3,
key_size=1024,
)
print(private_key_sample033.key_size)
# ==============================================================
# ==============================================================
# 暗号鍵による署名と公開鍵(public key)による検証、否認防止
sign_text = b"This is text for signature."
signature = private_key_sample033.sign(
sign_text,
# 暗号鍵による署名と公開鍵(public key)による検証
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
sign_text2 = b"This is text for signature2."
print("署名: " + str(signature))
public_key = private_key_sample033.public_key()
public_key.verify(
signature,
sign_text,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("\n")
# ==============================================================
# ==============================================================
# メッセージ認証
plain_text = "暗号化テキスト"
print("元の文:\t\t\t\t\t" + plain_text)
plain_text_byte = base64.b64encode(plain_text.encode())
print("元の文のバイナリデータ:\t" + str(plain_text_byte))
public_key = private_key_sample033.public_key()
crypted_text = public_key.encrypt(plain_text_byte,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
))
print("暗号化の文:\t" + str(crypted_text))
decrypted_text_byte = private_key_sample033.decrypt(crypted_text,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
))
print("復号したバイナリデータ:\t" + str(decrypted_text_byte))
decrypted_text = base64.b64decode(decrypted_text_byte).decode()
print("戻した文:\t\t\t\t" + decrypted_text)
# ==============================================================
秘密鍵の作成では、公開指数と鍵のサイズを指定。公開指数は65537(2の16乗+1)がデフォルトのよう。適当な数字を入れると、ValueError: public_exponent must be either 3 (for legacy compatibility) or 65537. Almost everyone should choose 65537 here! とのエラーが出る。3でもできた。
秘密鍵は、所有者が厳密に保管するため、例えば、所有者のデータをこれで署名して配布する場合、その署名されたデータが公開鍵で検証できれば、所有者本人のデータと分かる。もしデータが改ざんされていれば、検証でエラーが出るはず。上のコードで、sign_textを署名した上で検証時にsign_text2を指定すると、cyptography.exceptions.InvalidSignature のエラーが出る。
暗号化・復号化では、送信側から公開鍵で暗号化したメッセージを送信、受信側が秘密鍵で復号する。上のコードの実行結果が下。日本語のままでは暗号化できなかったので一端バイナリデータへ変換している。
公開鍵は誰でもアクセスできるので、購買者から送信される情報を暗号化して送信、通販ウェブサイトの管理者とか(秘密鍵の所有者)が復号化といった使い方になると思う。もし、暗号化された情報が漏れても、秘密鍵をもたない第3者では復号化することはできないため内容が漏れることはない。
Pythonを使ったちょっとした試し。