【Blockchain】トランザクションへの電子署名の実装

import pandas as pd
import datetime
from ecdsa import SigningKey, SECP256k1
import binascii
import json

secret_key_A_str = "47c5c280197c691be3f80462b72d60b7b2915753f1a81a6eedbfbb2f01f55cae"
public_key_B_str = "02cfbf50fe5873ac6e5352e7524c4934e32f01281fc7d6112fed86cf58e72b09bb302f1f7d10d7c37d13eb7e62fd8bb1950b263c51ac76581f8b0a38d0d8853e"

secret_key_A = SigningKey.from_string(binascii.unhexlify(secret_key_A_str), curve=SECP256k1)
public_key_A = secret_key_A.verifying_key
public_key_A_str = public_key_A.to_string().hex()
time_now = datetime.datetime.now(datetime.timezone.utc).isoformat()

unsigned_transaction = {"time": time_now, "sender": public_key_A_str, "receiver": public_key_B_str, "amount": 3}
signature = secret_key_A.sign(json.dumps(unsigned_transaction).encode('utf-8'))
transaction = {"time": time_now, "sender": public_key_A_str, "receiver": public_key_B_str, "amount": 3, "signature": signature.hex()}

pd.to_pickle(transaction, "signed_transaction.pkl")

取引記録の検証

import pandas as pd
from ecdsa import VerifyingKey, BadSignatureError, SECP256k1
import binascii
import json

transaction = pd.read_pickle("signed_transaction.pkl")
public_key_A = VerifyingKey.from_string(binascii.unhexlify(transaction["sender"]), curve=SECP256k1)
signature = binascii.unhexlify(transaction["signature"])

unsigned_transaction = {
	"time": transaction["time"],
	"sender": transaction["sender"],
	"receiver": transaction["receiver"],
	"amount": transaction["amount"]
}

try:
	public_key_A.verify(signature, json.dumps(unsigned_transaction).encode('utf-8'))
	print("トランザクションは改竄されていません。")
except BadSignatureError:
	print("トランザクションは改竄されています。")

$ python3 verify_transaction.py
トランザクションは改竄されていません。

cheat.py

import pandas as pd

transaction = pd.read_pickle("signed_transaction.pkl")
print("改竄前のトランザクション:")
print(transaction)

transaction = {"time": transaction["time"], "sender": transaction["sender"], "receiver": transaction["receiver"], "amount": 30, "signature": transaction["signature"]}
print("改竄後のトランザクション:")
print(transaction)
pd.to_pickle(transaction, "signed_transaction.pkl")

改竄するとsignatureが変更されていないので、改竄されていることがわかる