Import libraries and generate public and private keys
In [1]:
import hashlib
import json
from collections import OrderedDict
from Crypto.PublicKey import RSA
from Crypto import Random
from pprint import pprint
# Generate an RSA of 2048 bits
random_generator = Random.new().read
# Alice RSA keys
alice_private_key = RSA.generate(2048, random_generator)
alice_public_key_pem = alice_private_key.publickey().exportKey(format='PEM')
# Bob RSA keys
bob_private_key = RSA.generate(2048, random_generator)
bob_public_key_pem = bob_private_key.publickey().exportKey(format='PEM')
In [2]:
# Create a very big string to sign using alice's private key
a_test_message = b'A short message'
a_large_message = b'aa' * 10000000
# This works on a smaller message without hashing but doesn't work as well on a large message
# alice_sign_msg = alice_private_key.sign(a_large_message, K=None)
# A better option is to hash the message and then sign it using Alice's private key
hash_message = hashlib.sha256(a_large_message).digest()
print(hash_message)
# Now sign this message using Alice's private key
alice_sign_msg = alice_private_key.sign(hash_message, K=None)
# Now verify the message using Alice's public key (assume from another user)
import_alice_public_key = RSA.importKey(alice_public_key_pem)
print(import_alice_public_key.verify(hash_message, alice_sign_msg)) # Evaluates to True
# Now lets try and evaluate it importing Bob's public key
import_bob_public_key = RSA.importKey(bob_public_key_pem)
print(import_bob_public_key.verify(hash_message, alice_sign_msg)) # Evaluates to False
# Also try a different message against the one received
a_dif_test_message = b'An incorrect short message'
hash_dif_message = hashlib.sha256(a_dif_test_message).digest()
print(import_alice_public_key.verify(hash_dif_message, alice_sign_msg)) # Evaluates to False
In [3]:
# Generate a simple transaction for Alice, assumming she has Bob's public key
transaction = {
'from_pk' : alice_public_key_pem,
'to_pk': bob_public_key_pem,
'cc_amount': 50
}
# Hash and generate signature using the sender's private key
hash_transaction = hashlib.sha256(bytes(str(transaction), encoding="UTF-8")).hexdigest()
signature = alice_private_key.sign(bytes(str(hash_transaction), encoding="UTF-8"), K = None)
# Add signature to the transaction message
transaction['signature'] = signature
## Send your transaction...
# Pretend it has been sent
received_transaction = transaction
# Extract the signature
received_signature = transaction['signature']
# Remove signature from the transaction and get hash
del received_transaction['signature']
hash_received_transaction = hashlib.sha256(bytes(str(received_transaction), encoding="UTF-8")).hexdigest()
public_key = RSA.importKey(transaction['from_pk'])
# Check if the signature matches
signature_check = public_key.verify(bytes(str(hash_received_transaction), encoding="UTF-8"), received_signature)
if signature_check:
print("The sender is who they claim to be.")
else:
print("The sender is not who you think it is.")
In [ ]: