Verifying Elliptic Curve Digital Signature with TRON Smart Contract

Overview

Elliptic Curve Digital Signature Algorithm(ECDSA) is a variant of the Digital Signature Algorithm (DSA) based on the elliptic curve cryptography. ECDSA is widely in the blockchains of TRON, Bitcoin and Ethereum used for transaction signature, consensus verification and many other aspects. It is one of the cornerstone algorithms of blockchain technology.

While explaining the principle of ECDSA, this article will also describe the two approaches of verifying the elliptic curve encryption digital signature in Solidity. These include the widely-used Solidity function — ecrecover, and the new function, batchvalidatesign, introduced in the TRON Solidity V 0.5.9 compiler.

Elliptic curve digital signature algorithm theory

Signature generation algorithm

ECDSA is a combination of ECC and DSA. The whole signature process is similar to DSA. The ECDSA signature consists of a pair of integers (r, s). The steps of how public and private keys calculate to sign the message are as follows:

1. Select an elliptic curve Ep(a, b), and a base point G;

2. Select a set of key pair, wherein the private key k is generated by a random number, and the public key K=kG is calculated by using the base point G;

3. Generate a random integer r (r < n), calculate the equation R = rG;

4. Calculate e = HASH(message, x, y);

5. Calculate s ≡ r - e * k (mod n)

6. Take the value of r and s as the signature. If either r or s is 0, then re-execute the process from step 3.

Signature verification algorithm

After receiving the message (message) and the signature (r, s), the recipient will:

1.first, calculate sG+H(message)P=(x1, y1), r1 ≡ x1 mod p.

2.then, verify r1 ≡ r mod p.

If the verification is established, then the signature verification is passed.

Use ecrecover for signature verification

ecrecover function

The complete function signature of ecrecover is:

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

which is a global function provided by the Solidity language. This function returns the address of signers according to the signature itself and the data.

The parameters required in ecrecover, r, s, and v, are from the sliced content of the signature:

r = signature[0:64]

s = signature[64:128]

v = signature[128:130]

slice function

function slice(bytes memory data, uint start, uint len) returns (bytes){    bytes memory b = new bytes(len);    for(uint i = 0; i < len; i++){        b[i] = data[i + start];    }    return b;}The full contract code is as follows://return the address according to the signature and and the datafunction validate(bytes32 hash, bytes signature) returns (address){    bytes memory signedString = signature;    bytes32  r = convertToBytes32(slice(signedString, 0, 32));    bytes32  s = convertToBytes32(slice(signedString, 32, 32));    byte  v1 = slice(signedString, 64, 1)[0];    uint8 v = uint8(v1) + 27;    return ecrecover(hash, r, s, v);}//slice functionfunction slice(bytes memory data, uint start, uint len) returns (bytes){    bytes memory b = new bytes(len);    for(uint i = 0; i < len; i++){        b[i] = data[i + start];    }    return b;}//convert bytes to bytes32function convertToBytes32(bytes memory source) returns (bytes32 result) {    assembly {        result := mload(add(source, 32))    }
}

Parallel signature verification using batchvalidatesign

The batchvalidatesign function is a unique function of TVM and will come into effect after the №32 proposal is adopted. The complete function signature is:

batchvalidatesign(bytes32 hash,bytes[] signatures,address[] addresses) returns(bytes32)

The function accepts three parameters:

1.Bytes32 hash, content of the signature to be verified

2.Bytes[] signatures, signature list

3.Address[] addresses, address list

The return value of the function: since multiple sets of signatures are verified in parallels, the return value is bytes32 type so that the results of the verification signature are completely returned. For example, a return value of 10100000000000000000000000000000 means that the first group and the third group of signature verifications are passed.

It is important to note that users must use TRON Solidity Compiler V 0.5.9 or above for the process. Since the function takes arrays as a parameter, ABIEncoderV2 therefore must be enabled.

Complete contract code:

pragma experimental ABIEncoderV2;contract BatchValidate {    function validatesign(bytes32 hash, bytes[] memory signatures,         address[] memory addresses) public returns(bytes32){        return batchvalidatesign(hash, signatures, addresses);    }}

Conclusion

Verifying signatures in traditional Solidity language requires a lot of overheads, and developers need to make type conversions and write their own slicing functions. In addition, since ecrecover can only return the address, extra work is required to further compare whether the restored address match the signer’s address. In contrast, the batchvalidatesign introduced in the TRON Solidity V0.5.9 makes signature verification in smart contracts far more intuitive for users. Furthermore, the introduction of parallel verification is also conducive to more use cases of the smart contracts in the future.

References

https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm

https://github.com/tronprotocol/tips/blob/master/tip-43.md

For more information

Github: https://github.com/tronprotocol

Telegram: https://t.me/troncoredevscommunity

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store