Signing Data In Blockchain Using Python

Signing is one of the predominate mechanism to verify the user where the transaction is digitally signed to authorize. After this, the actual submission to the network occurs via the connected server. Finally, the verification is performed to ensure that the transaction is validated successfully.

Let's examine the fundamentals of public and private keys to better understand why they are crucial to blockchain technology.

Private Key: its a randomly generated number that is kept secret and held privately by the user. Depending on the kind and class of algorithms, private keys can have a variety of lengths. For example, in RSA, typically, a key of 1024-bit or 2048-bits is used. 1024-bit key size is no longer considered secure and at least 2048 bit is recommended to be used in practice.

Public Key: A public key is the public part of the private public key pair. A public key is available publicly and published by the private key owner.

On the other hand, you could say that the recipient's private key decrypts the data while the recipient's public key encrypts the same data and also you let the public key be given out in public. you tell everyone ,hey ,this is my Pk.

Digital Signature:

what we want from digital signature

  • Only you can sign but any one can verify
  • Signature is tied to a particular document
  • Can’t be cut and paste to another document
API for digital signatures

(sk ; pk ) := generateKeys(keySize)

sk : Secret signing key

pk : Public verification key

sig := sign(sk ; message)

isValid : = verify(pk ; message; sig)


Requirements for Signatures

Valid Signatures Verify

verify(pk ; message; sign(sk ; message)) == true


Can’t forge signatures

Adversary who, knows pk , gets to see the signature of his own choice, can’t produce a verifiable signature on another message.

let's generate the private key ; we need openssl software and window 10 OS .Dora generates the private key ,which is the dorakey.pem file and she keep this key secret . its generated by below command.

D:\KnowledgeHunt\blockchain\ch1> openssl genrsa -out dorakey.pem 1024


Now Dora generates the public key by below command

D:\KnowledgeHunt\blockchain\ch1> openssl rsa -in dorakey.pem -pubout > dorakey.pub


First , let's create the a python Virtual environment by the following commands

python -m venv blockchain

type > blockchain\Scripts\activate

(blockchain) D:\KnowledgeHunt\blockchain\ch1>pip install --upgrade pip

Requirement already satisfied: pip in d:\knowledgehunt\blockchain\ch1\blockchain\lib\site-packages (22.3.1)

(blockchain) D:\KnowledgeHunt\blockchain\ch1>pip install cryptography

Collecting cryptography

  Downloading cryptography-38.0.4-cp36-abi3-win_amd64.whl (2.4 MB)

     ---------------------------------------- 2.4/2.4 MB 303.4 kB/s eta 0:00:00

Collecting cffi>=1.12

  Downloading cffi-1.15.1-cp311-cp311-win_amd64.whl (179 kB)

     ---------------------------------------- 179.0/179.0 kB 1.2 MB/s eta 0:00:00

Collecting pycparser

  Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)

     ---------------------------------------- 118.7/118.7 kB 384.6 kB/s eta 0:00:00

Installing collected packages: pycparser, cffi, cryptography

Successfully installed cffi-1.15.1 cryptography-38.0.4 pycparser-2.21


When you run the below snippet and no exception is raised, that means you have successfully verified the signature using the public key and signature generated by Dora, you need a private key in order to create the signature. Also you can refer the above pseudocode that improves your clarity and it will help you understand how to verify a signature.

File hierarchy as below 

(blockchain) PS D:\KnowledgeHunt\blockchain\ch1> tree /F
Folder PATH listing for volume New Volume
Volume serial number is 8413-049D
D:.
│   dorakey.pem
│   dorakey.pub
│   messageValidate.py
│   messageVerify.py
└───blockchain

messageVerify.py

from cryptography.hazmat.primitives import hashes

from cryptography.hazmat.primitives.asymmetric import padding

from cryptography.hazmat.backends import default_backend

from cryptography.hazmat.primitives.asymmetric import rsa

from cryptography.hazmat.primitives import serialization

# BASIC Configuration

GENERATE_PRIVATE_KEY = False

PUBLIC_KEY_FROM_PRIVATE_KEY = False

PRIVATE_KEY = "dorakey.pem"

PUBLIC_KEY = "dorakey.pub"

MESSAGE = b"dora is the favourite character"

if GENERATE_PRIVATE_KEY:

    # Generate private key

    private_key = rsa.generate_private_key(

        public_exponent=65537,

        key_size=2048,

        backend=default_backend()

    )

else:

    # Load private key from pem file

    with open(PRIVATE_KEY, "rb") as key_file:

        private_key = serialization.load_pem_private_key(

            key_file.read(),

            password=None,

            backend=default_backend()

        )

signature = private_key.sign(

    MESSAGE,

    padding.PSS(

        mgf=padding.MGF1(hashes.SHA256()),

        salt_length=padding.PSS.MAX_LENGTH

    ),

    hashes.SHA256()

)

if PUBLIC_KEY_FROM_PRIVATE_KEY:

    # Getting public key from private key

    public_key = private_key.public_key()

else:

    # Load public key from file

    with open(PUBLIC_KEY, "rb") as key_file:

        public_key = serialization.load_pem_public_key(

            key_file.read(),

            backend=default_backend()

        )

public_key.verify(

    signature,

    MESSAGE,

    padding.PSS(

        mgf=padding.MGF1(hashes.SHA256()),

        salt_length=padding.PSS.MAX_LENGTH

    ),

    hashes.SHA256()

)

# Print signature hashes.SHA256 Algo

#print(signature)

Now,It's time to confirm whether or not Dora actually wrote the message ,so below snippet will help to validate the our process.

messageValidate.py

from cryptography.hazmat.backends import default_backend

from cryptography.hazmat.primitives.asymmetric import rsa

from cryptography.hazmat.primitives import serialization

from cryptography.hazmat.primitives import hashes

from cryptography.hazmat.primitives.asymmetric import padding

# opens the file in binary format for reading and module contains functions for loading keys

with open("dorakey.pub", "rb") as key_file:

        real_public_key = serialization.load_pem_public_key(

           key_file.read(),

           backend=default_backend())

# Message coming from user

message = b"dora is the favourite character" # you can change message and check response as well 

# Signature coming from user

signature = b'B\x00W\xf2\xfda}\xd0HBb\xa8\x13TB\x87\xd8\xdf9\xd0\x91o\x93v\xa9\x968MG+\x9d\x8fz\xb5\xbf\xcc\xce4d\xa0z+\xde\x9e;xdx\xbf\x15O\xc3\x91\xc8\xfa\xaa\xe9\x8e)\xfe)<\x1d\xffK@N\xe6f\xaf\x17\x1c\x0c\xc5\xe8D\xee\xc3\xbf\xcb^\xa7k\x7f\xc9\xdcU\xce`a\x0fw\x0f\x19\x94{\xb3\x992N\x19\x0c\x87\xce\x0b\x19u\x07\xa4\xf7g@\xb0O4\xb29\xa1\xe6H\xa8]\xdd\xc8\xb8\xbb7S'

user = message.split()[0].lower()

# fetch public key from Dorakey

public_key = real_public_key

# … verify the message like before

public_key.verify(

    signature,

    message,

    padding.PSS(mgf=padding.MGF1(hashes.SHA256()),

                salt_length=padding.PSS.MAX_LENGTH),

    hashes.SHA256())    

#If this script returns no errors, your algorithm successfully verified the user based on the message and signature. 

I have changed the message  b"Tara is the favourite character" but not signature and run the above script 

(blockchain) PS D:\KnowledgeHunt\blockchain\ch1> python .\messageValidate.py

Traceback (most recent call last):

  File "D:\KnowledgeHunt\blockchain\ch1\messageValidate.py", line 24, in <module>

    public_key.verify(

  File "D:\KnowledgeHunt\blockchain\ch1\blockchain\Lib\site-packages\cryptography\hazmat\backends\openssl\rsa.py", line 569, in verify

    _rsa_sig_verify(

  File "D:\KnowledgeHunt\blockchain\ch1\blockchain\Lib\site-packages\cryptography\hazmat\backends\openssl\rsa.py", line 325, in _rsa_sig_verify

    raise InvalidSignature

cryptography.exceptions.InvalidSignature 

This implies that each message has a unique signature that cannot be determined by the recipient.

Please add your suggestions if any :) 

Comments