Ethereum: How are SIGHASH flags encoded into a signature?

Ethereum: How Are SIGHASH Flags Encoded Into a Signature?

In Ethereum, signatures are used to prove ownership and authorship of transactions on the blockchain. One of the key components that enables this is the
SIGHASH (Signature Hash Algorithm) flags system. In this article, we’ll delve into how SIGHASH flags are encoded into a signature.

What are SIGHASH flags?

SIGHASH flags allow the signer to control which parts of the transaction they want to sign and verify. These flags enable more efficient use of memory and computation resources on the Ethereum network. A
signature is created by hashing the input data with the public key, followed by hashing the resulting hash with the private key.

Encoding SIGHASH flags into a signature

When a signer wants to extract specific parts of the transaction to sign, they need to encode their SIGHASH flag into a unique identifier that can be used for verification. This is done by extracting the required field from the input data and then hashing it with the private key.

Let’s assume we’re working with a simple transaction example:

pragma solidity ^0.8.0;

contract SimpleTransaction {

function sendMoney(address recipient, uint amount) public {

// Input: sender, recipient, and amount to transfer

bytes32 _inputs = abi.encodePacked(sender, recipient, amount);

// Encode SIGHASH flags (OP_CHECKSIG)

SIGHASH[] memory _flags = new SIGHASH[_inputs.length];

for (uint i = 0; i < _inputs.length; i++) {

_flags[i] = SIGHASH(_inputs[i]);

}

// Hash the input data with the private key

bytes32 _dataHash = abi.encodePacked(_inputs, msg.sender);

// Hash the result with the public key (OP_CHECKSIG)

bytes32 _sigHash = keccak256(abi.encodePacked(_dataHash, _flags));

// Sign the signature hash with the private key

bytes32 _sig;

if (msg.sender == address(0)) {

assembly {

_sig := sha3_256(memo := abi.encodePacked(_sigHash))

}

} else {

_sig := keccak256(abi.encodePacked(_sigHash));

}

// Verify the signature

require(msg.sender == owner, "Invalid signature");

}

}

In this example, we’re encoding the SIGHASH flags into a unique identifier using the abi.encodePacked function. We’re also hashing the input data with the private key to create the hash value.

SIGHASH flag encoding

The _flags array contains one element per flag, which is a
SIGHASH structure that includes information such as:

  • 0x1 (OP_CHECKSIG): Extracts the non-stack argument from each signature it evaluates.

  • Other flags (e.g., OP_CHECKSIGVERIFY, OP_CHECKSIGSIGN): Provide additional verification options.

By encoding these flags into a unique identifier using the _sigHash variable, we can verify that the correct part of the transaction was signed and verified.

Conclusion

In this article, we’ve explored how SIGHASH flags are encoded into a signature in Ethereum. By understanding how these flags work, you’ll be better equipped to optimize your code for better performance on the network. Remember to always follow best practices when working with cryptography and hash functions.

ETHEREUM ALERT UPGRADE REQUIRED