Solidity Smart Contract To Implement Message Signature And Verification: Let's code series

 


When we talk about signatures, the first thing that comes into our mind is the attestation and validation of a document or an asset from an authorized person. The concept of signature dates back to 3000 BC, it was originated from the Egyptian cultures in the form of small symbols, seals or complex patterns. Still in the modern days, the transaction of paper money is accomplished via cheques which is only valid if it has the signature of the owner of that bank account.

With the advancement in tracing technology the hand written signatures became vulnerable and easy to bypass, so techies came up with the concept of digital signatures.

WHAT IS A DIGITAL SIGNATURE:





"A digital signature is a mathematical scheme for verifying the authenticity of digital messages or documents."

Keeping in mind the concept of digital signature when we are talking about the blockchain eco-system, we can use this technique to sign the messages passing between the nodes and verify them by writing a smart contract. So let's jump right into it.

Prerequisites:

i) Basic understanding of Solidity
ii) Remix online IDE
iii) Meta mask chrome plugin
iv) Ganache application



Setting up Ganache with remix:

In order to connect remix with ganache, first make sure that ganache is up and running on localhost.

Inside remix deploy panel click on the Environment drop down list and select "Web3 Provider", it'll then prompt you to enter a valid rpc url. Enter your ganache rpc url and your remix IDE will be connected to ganache account.

NOW TIME TO CODE:

I'll break down the smart contract functions into small headings to explain what is happening.

i) Hashing the Message:


This function encrypts the message using Keccak256 algorithm which returns a 32 byte code hash value. The arguments of this function includes: 

i) The address of the message receiver account 

ii) Amount of transaction

iii) Message in string notation

iv) Nonce (Number only used once) a number added in the hash string which strict the use of that hash again to ensure preventing the bypass.

Pure modifier is used in this function to ensure that the state of this function can not be modified.

ii) Signing the hash of the message:




This function expects the hash of the message we just created and and signs that hash using keccak256. You'll get clearer picture when i'll explain the usage of this function in the verification.

iii) Verification: Now the verification is the most interesting part of this whole journey, we verify a message by comparing the signer extracted from the signed hash we created in the previous step with the signer recovered from the signature produced from ECDSA cryptographic algorithm using the built in global solidity function ecrecover.


Here the first argument is the signed hash we made in step 2 while the second argument is the signature which we'll produce using ECDSA algorithm.

Now the elephant in the room is the presence of these 3 variables r,s,v, for that we need to understand the working of splitSignature function and why are we splitting the signature in these three components.

According to the documentation of web3, this ecrecover function works over the principle of Elliptic curve cryptography and this function requires total of 4 arguments which includes the signed hash and the three splitted component. The ecrecover function essentially recovers the signer of the signature.

iv) Splitting the signature:


The splitting of the bytes is done using the assembly language which is again a standard protocol proposed to this date and to my knowledge. Here mload is used to load the bytes from the memory to the variable, the add keyword here signifies that we are skipping first 32 bytes because dynamic arrays store the length of the array in the first 32 bytes, similarly for "s" we skip first 64 bytes in order to avoid the length of array and the bytes assigned to "r" and similarly goes for the variable "v".


Our final piece of the puzzle is the function verify itself, so its arguments includes the address of the original signer from the beginning, original amount, message, nonce value and finally the signature produced from ECDSA algorithm, let's talk about generating this signature from the browser console.

First we connect out ganache account with metamask, but HOW???

Step 1) Install metamask chrome extension
Step 2) Select localhost account from the dropdown, make sure your ganache port is similar to that presented in meta mask drop down, in my case it is localhost:8545



Step 3) Click on your account avatar and select the import account option

Step 4) Enter your ganache private key into the account form of metamask import account prompt


If you can see the 100 ethers in your account 2 then it indicates that you have successfully connected a ganache account to metamask

i) Compile and deploy your contract with web3 Provider environment


Your deployed contract should look like this:


ii) Copy the address of account 2 and paste it in the getMessageHash first argument, enter the amount, message and nonce value=1


Calling this function returns a byte32 hash, copy it.

iii) Open your chrome console window and execute following commands

>etherium.enable()
this opens your metamask extension and asks you to login.

>hash="paste your copied hash inside these string quotes"

>web3.personal.sign(hash,web3.eth.defaultAccount,console.log)
this function takes the hash variable as the first argument, calls the address of the account with which you deployed the contract as the second argument and finally console.log to log the ECDSA signature as third argument. 

Executing this function will open metamask prompt to confirm signing. 

>web3.eth.defaultAccount
executing this code returns the address of the account with which the contract was deployed


iv) Now to verify the signature, copy the defaultAccount address and paste it as the first argument of verify function, then copy the argument entries of getMessageHash function we entered previously and paste it in the next three arguments of verify(), finally for the last argument copy the signature from the console and paste it as the last argument.




The returned value true indicates that the original signer and the signer recovered from the signature are matched and verified, to test the security let's change the message from "hello world" to "hello cruel world" and see if returns false.


That's it, you just successfully implemented a Message signature and verification smart contract using solidity.












 























Comments