The Lisk protocol uses the Ed25519 signature scheme (see Wikipedia page and the specification page for Ed225519). The signing procedure uses the message and the private key of the signer to generate 64 bytes, called the signature. Other users can then verify this signature with respect to the message and the public key of the signer.
In the Lisk protocol the procedure for signing blocks and transactions is as follows:
Serialize the object into the corresponding binary message.
Prepend the 32 bytes network identifier to the binary message (see LIP 0009 and LIP 0024). The network identifier uniquely binds a transaction or a block to one network. Different blockchains created with the Lisk SDK should use different network identifiers to avoid transaction replay between chains.
Compute the signature of the output of step 2 above, as described in the Ed25519 specifications.
The network identifier is not transmitted with the binary message. The procedure to verify transactions is therefore as follows:
Remove the signature from the object received.
Serialize the output of step 1 to a binary message.
Prepend the network identifier to the binary message.
Verify the output of step 3 with respect to the signature and the signer public key.
The Lisk ecosystem uses IDs to identify objects, such as blocks and transactions. The ID is obtained by serializing the object, including the signature, and taking the SHA-256 (Secure Hash Algorithm 256), hash. See the Wikipedia page of this binary message.
Key pair and address creation
To create a new address, first a 12-word passphrase is generated following the specifications of BIP39. The passphrase is then hashed using the SHA-256 into a 256-bit string. The resulting hash is used as the seed to generate the private key and the public key using Ed25519 signature scheme. Finally, the address is generated by taking the first 20 bytes of the SHA-256 hash of the public key.
We display addresses in their Lisk32 representation which includes a checksum and the "lsk" prefix. The procedure to obtain the Lisk32 representation of an address is as follows:
Calculate a 30-bit checksum of the address of the account using a BCH code, see BIP173. This step provides protection against accidental typing mistakes.
Concatenate the address and the output of step 1.
Encode the output of step 2 in a custom Base32 format, see LIP 0018 for details. Lower-case letters and digits are used, the characters i, l, 1 and 0 are removed for usability reasons.
Add the prefix "lsk" to the output of step 3. This ensures that the Lisk32 representation used in the Lisk wallet start with "lsk" and that the final address is 41 characters long.
As an example, the address
0xc247a42e09e6aafd818821f75b2f5b0de47c8235 has the Lisk32 representation