Hello,
In this thread, I want to propose a LIP for the roadmap objective “Allow for memory-efficient signing”. The proposal’s main contribution is to introduce a pre-hashing step in the signing process.
I’m looking forward to your feedback.
Here is a complete LIP draft:
LIP: <LIP number>
Title: Use pre-hashing for signatures
Author: Maxime Gagnebin <maxime.gagnebin@lightcurve.io>
Type: Standards Track
Created: <YYYY-MM-DD>
Updated: <YYYY-MM-DD>
Requires: 0037
Abstract
This LIP introduces pre-hashing for signatures in Lisk, this includes transactions, block headers and certificate signatures. This allows signing to be performed on memory limited devices such as hardware wallets.
Copyright
This LIP is licensed under the Creative Commons Zero 1.0 Universal.
Motivation
Introducing memory efficient signing allows all objects used in the Lisk protocol to be signed on devices with limited memory. Most of the current transactions have a small size and can be signed on existing devices. However, new transactions implemented in the interoperability module, or transactions implemented in decentralized applications are likely to be too large to be signed directly on such devices. This argument was overlooked in the past which led to the pre-hashing step being removed in LIP 0008.
With the current proposal, signatures are computed against the hash of the message to be signed and hence always computed for a byte string of small constant size.
Rationale
Choice of Hash Function
Hashing before signing is a common practice and different protocols use different hash functions for this task. For the Lisk protocol, the natural choice of hash function is SHA-256. This function is used in multiple other parts of the protocol and hence it makes sense to not expose the protocol to another hash function.
Introduction of another hash function to the Lisk protocol was suggested in LIP 0010, but was later withdrawn as SHA-256 is widely used and can be considered secure.
On Removing Pre-hashing in LIP 0008
LIP 0008 removed the pre-hashing step from the Lisk signing protocol. This was mainly done as this step was deemed unnecessary and removing it could improve the theoretical security of the signing process. However this is not reflected by a practical improvement in protocol security as the SHA-256 hash function is considered collision resistant and secure. This hash function is used in several critical parts of many applications, including Lisk, and any future findings that SHA-256 is insecure would require changing the protocol throughout.
Specification
The signature for a binary message message
and a secret key sk
is generated by signMessage(sk, tag, networkIdentifier, message)
as defined below. tag
must be the correct message tag for message
as defined in LIP 0037, and networkIdentifier
the correct network identifier for the chain. The resulting signature signature
in combination with the message message
and the matching public key pk
is verified by verifyMessageSig(pk, tag, networkIdentifier, message, signature)
.
signMessage(sk, tag, networkIdentifier, message):
taggedMessage = tag || networkIdentifier || message
hashedMessage = hash(taggedMessage)
return Sign(sk, hashedMessage)
verifyMessageSig(pk, tag, networkIdentifier, message, signature):
taggedMessage = tag || networkIdentifier || message
hashedMessage = hash(taggedMessage)
return Verify(pk, hashedMessage, signature)
Where hash
is the SHA-256 hash digest of the input, and the functions Sign
and Verify
are the signing and verifying functions of the respective signature scheme.
Signing and Verifying with Ed25519
For the Ed25519 signature scheme, Sign
and Verify
are the signing and verifying functions as specified in RFC 8032.
The signMessage
and verifyMessageSig
functions defined in LIP 0037 are superseded by the functions defined in this LIP.
Signing and Verifying with BLS
For the BLS signature scheme used in Lisk, Sign
(identical to CoreSign
) and Verify
(identical to CoreVerify
) are the signing and verifying functions as specified in BLS Signatures draft-irtf-cfrg-bls-signature-04.
The signBLS
and verifyBLS
functions defined in LIP 0038 are superseded by the functions defined in this LIP.
Reference Implementation
TBD
Backwards Compatibility
This LIP results in a hard fork as nodes following the proposed protocol will reject signatures according to the previous protocol, and nodes following the previous protocol will reject signatures according to the proposed protocol.