KIP: 5
Layer: Applications
Title: Message Signing
Author: coderofstuff
Status: Active
Signing messages provides a mechanism for proving access to a given address without revealing your private keys. This paves the way for proving ownership of funds, native assets (not implemented yet) among many possible use-cases.
This document aims to provide a standard which applications can implement their message signing and verification functionalities.
This part of the process is relevant to applications that have access to the private key and will sign some message.
Given:
- A string of arbitrary length. We'll call this
raw_message
- A
private_key
Output: signature associated with that string with some given private key
- Hash the message using Blake2B. To create sufficient domain separation with transaction input sighash, use a different Blake2B key
PersonalMessageSigningHash
(Transaction hashes usesTransactionSigningHash
as key to blake2b) and a digest length of32
- Schnorr sign the hashed message
In summary: schnorr_sign(blake2b(raw_message, digest_size=32, key='PersonalMessageSigningHash'), private_key)
- Reduces the size of some arbitrary message to a fixed length hash
- Prevents signing of sighashes accidentally - the raw message is hashed with a different blake2b key (
PersonalMessageSigningHash
) from what is used for transaction hashes (TransactionSigningHash
), creating sufficient domain separation
This part of the process is relevant to applications that is asking some public_key owner to provide evidence that they have access to the private_key of this public_key.
Given:
- A string of arbitrary length. We'll call this
raw_message
- A
public_key
which the application has asked to sign the message
Output: true
if the signature is valid, false
otherwise
- Hash the raw message in the same way as above for signing
- Schnorr verify the signature matches the
public_key
you are testing for
In summary: schnorr_verify(blake2b(raw_message, digest_size=32, key='PersonalMessageSigningHash'), public_key)
Full code in /kip-0005/test-cases.py
from hashlib import blake2b
from secp256k1 import PublicKey, PrivateKey
# Assume we have a private-public key pair
# some_secret_key (private) and some_public_key (public)
def hash_message(raw_message) -> bytes:
message_hash = blake2b(digest_size=32, key=bytes("PersonalMessageSigningHash", "ascii"))
message_hash.update(raw_message)
return message_hash.digest()
def sign_message(raw_message) -> bytes:
message_digest = hash_message(raw_message)
return PrivateKey(some_secret_key).schnorr_sign(message_digest, None)
def verify_message_signature(raw_message, message_signature) -> bool:
message_digest = hash_message(raw_message)
return PublicKey(some_public_key).schnorr_verify(message_digest, message_signature, None)
Keys taken from https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv
index | secret key | public key | aux_rand | message_str | signature |
---|---|---|---|---|---|
0 | 0000000000000000000000000000000000000000000000000000000000000003 | F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9 | 0000000000000000000000000000000000000000000000000000000000000000 | Hello Kaspa! | 40B9BB2BE0AE02607279EDA64015A8D86E3763279170340B8243F7CE5344D77AFF1191598BAF2FD26149CAC3B4B12C2C433261C00834DB6098CB172AA48EF522 |
1 | B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF | DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659 | 0000000000000000000000000000000000000000000000000000000000000001 | Hello Kaspa! | EB9E8A3C547EB91B6A7592644F328F0648BDD21ABA3CD44787D429D4D790AA8B962745691F3B472ED8D65F3B770ECB4F777BD17B1D309100919B53E0E206B4C6 |
2 | B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF | DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659 | 0000000000000000000000000000000000000000000000000000000000000001 | こんにちは世界 | 810653D5F80206DB519672362ADD6C98DAD378844E5BA4D89A22C9F0C7092E8CECBA734FFF7922B656B4BE3F4B1F098899C95CB5C1023DCE3519208AFAFB59BC |
3 | B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF | DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659 | 0000000000000000000000000000000000000000000000000000000000000001 | (See Test CAse 3 Full Text section) |
40CBBD3938867B10076BB14835557C062F5BF6A4682995FC8B0A1CD2ED986EEDAAA00CFE04F6C9E5A9546B860732E5B903CC82780228647D5375BEC3D2A4983A |
Lorem ipsum dolor sit amet. Aut omnis amet id voluptatem eligendi sit accusantium dolorem 33 corrupti necessitatibus hic consequatur quod et maiores alias non molestias suscipit? Est voluptatem magni qui odit eius est eveniet cupiditate id eius quae aut molestiae nihil eum excepturi voluptatem qui nisi architecto?
Et aliquid ipsa ut quas enim et dolorem deleniti ut eius dicta non praesentium neque est velit numquam. Ut consectetur amet ut error veniam et officia laudantium ea velit nesciunt est explicabo laudantium sit totam aperiam.
Ut omnis magnam et accusamus earum rem impedit provident eum commodi repellat qui dolores quis et voluptate labore et adipisci deleniti. Est nostrum explicabo aut quibusdam labore et molestiae voluptate. Qui omnis nostrum At libero deleniti et quod quia.