MANUAL.md

April 10, 2021 ยท View on GitHub

Manual

This document shows how to use basic commands with musign.

Generate a public key

$ musign-generate 
Generate a public key from a secret (private key/seed/secret key). In case of btc-legacy type p2pkh
address is generated

USAGE:
    musign generate [OPTIONS] [secret]

ARGS:
    <secret>    Secret (also known as seed, private key or secret key) in hex. Alternatively,
                the key can be provided via STDIN

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -t <sig-type>        Type of signature [default: ecdsa] [possible values: ecdsa, schnorr, btc-
                         legacy]

From a random 32 byte seed (private key) we can generate a public key for usage with ECDSA

$ musign generate 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b

{"pubkey":"03dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59"}

or for usage with Schnorr signatures:

$ musign generate -t schnorr 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b

{"pubkey":"dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59"}

For usage with btc legacy signatures a p2pkh address is returned:

$ musign generate -t btc-legacy 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b

{"address":"12dR2srvCmffup7yBu5fdb3qkhFudTBnvZ"}

Sign a message

musign-sign 
Sign a message. Signature is returned

USAGE:
    musign sign [OPTIONS] <msg>

ARGS:
    <msg>    Message to sign

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -r <format>             Output format [default: json] [possible values: json, cbor]
    -f <seckey-file>        Path to private key (Not implemented)
    -s <secret>             Private key in hex. Alternatively, the key can be piped via STDIN
    -t <sig-type>           Signature type [default: ecdsa] [possible values: ecdsa, schnorr, btc-
                            legacy]

Signing a message which returns an ECDSA signature in JSON format:

$ musign sign "Hello world!" -s 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b

{"sig_type":"ECDSA","signature":"12341336cb664828bcd15de1bcf13667ed995d100d1a1b3ece9c0c6691d894072cc227014626ea034d2371cdfa0e261f557d3f72d2cfcc2fe0756f5c5c71faba","message":"Hello world!","pubkey":"03dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59"}

If we choose CBOR format:

$ musign sign "Hello world!" -s 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b -r cbor

a4687369675f7479706565454344534163736967984012183413183618cb18661848182818bc18d1185d18e118bc18f11836186718ed1899185d100d181a181b183e18ce189c0c1866189118d8189407182c18c21827011846182618ea03184d1823187118cd18fa0e1826181f1855187d183f187218d218cf18cc182f18e01875186f185c185c187118fa18ba676d6573736167656c48656c6c6f20776f726c6421667075626b65797842303364633561346661663839616437313837393333303432626363306664303238623332393666383265376130663137656563636562346637383761653333663539

This translates to CBOR diagnostic notation as:

{"sig_type": "ECDSA", "sig": [18, 52, 19, 54, 203, 102, 72, 40, 188, 209, 93, 225, 188, 241, 54, 103, 237, 153, 93, 16, 13, 26, 27, 62, 206, 156, 12, 102, 145, 216, 148, 7, 44, 194, 39, 1, 70, 38, 234, 3, 77, 35, 113, 205, 250, 14, 38, 31, 85, 125, 63, 114, 210, 207, 204, 47, 224, 117, 111, 92, 92, 113, 250, 186], "message": "Hello world!", "pubkey": "03dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59"}

Signing a message with Schnorr returns a Schnorr signature in JSON:

$ musign sign -t schnorr "Hello world!" -s 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b

{"sig_type":"Schnorr","signature":"22c2cfbaaee968a7afb6bfcd847b830e373ac066021d7286ade84ab5f64f8a4f7e0371c19f06e54f150dd4c98ebb631cb660389d8120e60f1dfa78a17aa3fc72","message":"Hello world!","pubkey":"dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59"}

Signing a message with Legacy BTC method:

$ musign sign -t btc-legacy -s 7694c743a0159ebfb79a65aae8970fcc5be5e9db8efa1ebf70218ae00bb1f29b "Hello world!"

{"sig_type":"BtcLegacy","signature":"IJIhzsY2hAFo613hTg9Gz4qc3ffWKVz3A+Wux8lwYSj5Vm1Mxqn5i7VTdhSuysrNAexNcSMBlkHyqOym77IiC/0=","message":"Hello world!","address":"12dR2srvCmffup7yBu5fdb3qkhFudTBnvZ"}

Verify a signature

musign-verify 
Verify a signature for a given message. True is returned for a valid signature otherwise false

USAGE:
    musign verify [OPTIONS] <signature> <message>

ARGS:
    <signature>    Signature in hex
    <message>      Message string

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -a <address>         BTC p2pkh address
    -p <pubkey>          Public key in hex. Alternatively, the key can be provided via STDIN
    -t <sig-type>        [default: ecdsa] [possible values: ecdsa, schnorr, btc-legacy]

Verifying an ECDSA signature:

$ musign verify 12341336cb664828bcd15de1bcf13667ed995d100d1a1b3ece9c0c6691d894072cc227014626ea034d2371cdfa0e261f557d3f72d2cfcc2fe0756f5c5c71faba "Hello world!" -p 03dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59

true

Verifying a Schnorr signature:

$ musign verify -t schnorr 22c2cfbaaee968a7afb6bfcd847b830e373ac066021d7286ade84ab5f64f8a4f7e0371c19f06e54f150dd4c98ebb631cb660389d8120e60f1dfa78a17aa3fc72  "Hello world!" -p dc5a4faf89ad7187933042bcc0fd028b3296f82e7a0f17eecceb4f787ae33f59

true

Verifying a BTC legacy signature with and address 12dR2srvCmffup7yBu5fdb3qkhFudTBnvZ

$ musign verify -t btc-legacy IJIhzsY2hAFo613hTg9Gz4qc3ffWKVz3A+Wux8lwYSj5Vm1Mxqn5i7VTdhSuysrNAexNcSMBlkHyqOym77IiC/0= "Hello world!" -a 12dR2srvCmffup7yBu5fdb3qkhFudTBnvZ

true

Multisignatures

Multisig-setup

musign-multisig-setup 
Set up a multisig: quorum and all the participants (pubkeys in hex)

USAGE:
    musign multisig-setup [OPTIONS] <threshold>

ARGS:
    <threshold>    Threshold

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -p <pubkeys>...        List of public keys to participate in a multisig in hex format.
                           Alternatively, the keys can be piped via STDIN
    -t <sig-type>          Signature type. Currently only ecdsa implemented [default: ecdsa]
                           [possible values: ecdsa, schnorr, btc-legacy]

Let's create a multisignature setup 2 of 3:

$ musign multisig-setup 2 -p 03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1 026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435 0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d > m_setup.json
echo $(<m_setup.json)
{"sig_type":"ECDSA","threshold":2,"pubkeys":["03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1","026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435","0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d"]}

multisig-construct-msg

musign-multisig-construct-msg 
Add message to a multisig setup. Returns an unsigned multisignature object

USAGE:
    musign multisig-construct-msg <msg> <setup>

ARGS:
    <msg>      Message to sign
    <setup>    Multisignature setup (JSON)

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

Now, we can create a multisignature object with a message to be signed with the participants of the multisignature setup:

$ musign  multisig-construct-msg "Hello world!" "$(<m_setup.json)" > m_obj.json
echo $(<m_obj.json)
{"msg":"Hello world!","setup":{"sig_type":"ECDSA","threshold":2,"pubkeys":["03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1","026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435","0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d"]}}

multisig-sign

$ musign-multisig-sign -h
musign-multisig-sign 
Sign a multisignature object passed via STDIN

USAGE:
    musign multisig-sign [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -s <secret>        Private key in hex to sign the multisig object. Alternatively, the key can be
                       provided via STDIN

We can now start signing our multisig object:

$ musign multisig-sign -s e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641 < m_obj.json > m_obj_signed1.json
$ musign multisig-sign -s aadd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641 < m_obj.json > m_obj_signed2.json
echo $(<m_obj_signed1.json)
{"msg":"Hello world!","setup":{"sig_type":"ECDSA","threshold":2,"pubkeys":["03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1","026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435","0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d"]},"signatures":["b762298fe57c79493630077f05b708b9e57498b0f6ffb950770a96144fe36f2955579bf40db6c32355aaf4eedd16713f3fe4d232714397b2fcc0d67953037969"]}

The JSON object is signed by first removing all the whitespaces. The order of JSON properties is preserved.

If we are passing in the object that already contains some signatures, the signatures are also removed before signing.

Note: only ECDSA signing in compact format is supported

multisig-combine

$ musign-multisig-combine -h
musign-multisig-combine 
Combine signatures of individually signed multisignature objects. Pass them via STDIN

USAGE:
    musign multisig-combine

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

Let's combine the signatures:

$ cat m_obj_signed1.json m_obj_signed2.json | musign multisig-combine > m_obj_signed_combined.json

Note: Combining signatures is not necessary if we had signed m_obj_signed1.json with the second private key.

multisig-verify

musign-multisig-verify 
Verify a multisignature object passed via STDIN. Returns true or false

USAGE:
    musign multisig-verify

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

Finally, we can verify our combined multisignature object:

$ musign multisig-verify < m_obj_signed_combined.json

true

This is our final object:

echo $(<m_obj_signed_combined.json)
{"msg":"Hello world!","setup":{"sig_type":"ECDSA","threshold":2,"pubkeys":["03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1","026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435","0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d"]},"signatures":["c71a9ae764c5f457c7d9ff0e7e11004e3c328492ab7894972f9e14403386b132267bb019a8d86a92f4dfefce26a3001d8c1995a284e0bb664573b9e3ada7b36c","b762298fe57c79493630077f05b708b9e57498b0f6ffb950770a96144fe36f2955579bf40db6c32355aaf4eedd16713f3fe4d232714397b2fcc0d67953037969"]}

Using Musign with Keytool

We can pipe a hex private or a public key generated with keytool into musign.

Single Signatures

Let's sign a simple message with a private key derived from a HD key with a derivation path of m/99h/1h/2h/2/0

$ keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-ec-key --full-address-derivation-path m/99h/1h/2h/2/0 | musign sign "Hello world!" > m_object.json


# the content of m_object.json:
{"sig_type":"ECDSA","signature":"a2aaa2d2d0b9a4cafa2af352c1344a762d795a8c3eddd201f5ade6c0a907e115418220301b1e8f37b88e8f5d8e19399c8e05ac14e2ef0c2915cc5d537de040c3","message":"Hello world!","pubkey":"038e4c0a6e918071b1e1b344ca1a2d72e2ba6147af70a222461e34b5c080e7a726"}

Let's verify the signature with the public key derived form the HD key in keytool:

keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-pub-ec-key --full-address-derivation-path m/99h/1h/2h/2/0 | musign verify "$(cat m_object.json | jq -r '.signature')" "$(cat m_object.json | jq -r '.message')"

true

Verify a Bitcoin Legacy Signature

Let's first create a signature

$ keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-ec-key --full-address-derivation-path m/99h/1h/2h/2/0 | musign sign "Hello world!" -t btc-legacy

{"sig_type":"BtcLegacy","signature":"IP1TzudsYCBkANtRiHpwZhTAOTldUyTNc5WZ/Ec5Jg6+dQi2f/wyUhNsF8QQJrTSwmiAIXBG6++DLs/MGz3a/IU=","message":"Hello world!","address":"1MYvHT6iaJdKq5ighZgqormkKWfPPHBMTR"}

Now we can verify a signature via P2PKH address

$ keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-pkh --full-address-derivation-path m/99h/1h/2h/2/0 | musign verify IP1TzudsYCBkANtRiHpwZhTAOTldUyTNc5WZ/Ec5Jg6+dQi2f/wyUhNsF8QQJrTSwmiAIXBG6++DLs/MGz3a/IU=  "Hello world!" -t btc-legacy

true

Multisignatures

Similarily, we can pipe keytool keys in hex into musign subcommands associated with multisignatures.

$ { keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-ec-key --full-address-derivation-path m/99h/1h/2h/0 && keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-ec-key --full-address-derivation-path m/99h/1h/2h/1; } | musign multisig-setup 2 > m_tmp.json

# m_tmp.json:
{"sig_type":"ECDSA","threshold":2,"pubkeys":["0fb01cbd70be8fcfaf11e64681d99a5d8490b8672ae587861709b21c5b6f9113","db20fa1bd20a2310d09f16e279743a2edf400ee9804cd62b86fde571a31fffe0"]}

When signing a multisig object we have to pipe the object itself and the private key:

$ { cat m_obj.json && keytool --seed 581fbdbf6b3eeababae7e7b51e3aabea address-ec-key --full-address-derivation-path m/99h/1h/2h/2/0;} | musign multisig-sign

{"msg":"Hello world!","setup":{"sig_type":"ECDSA","threshold":2,"pubkeys":["03c2805489921b22854b1381e32a1d7c4452a4fd12f6c3f13cab9dc899216a6bd1","026586cae2ee70f6f046f63ce2e7e3b479099c61753cf7d913f2eab2e78df5a435","0350f1f0017a468c993b046442438e5340b6675376663b7f653fd03f667488c60d"]},"signatures":["5f18db844afe9ca5f61b4da47a422d1d34c2d0bbb590d413757646a1f32ac10d706134b6f8f33b0ebdafc5afdd3ddecc45103cab9554735f121cfe582df1b788"]}

Help

$ musign -h
musign-cli 
Generate secp256k1 keys, sign and verify messages with ECDSA and Schnorr in a single- or
multisignature setup

USAGE:
    musign <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    generate                  Generate a public key from a secret (private key/seed/secret key).
                              In case of btc-legacy type p2pkh address is generated
    help                      Prints this message or the help of the given subcommand(s)
    sign                      Sign a message. Signature is returned
    verify                    Verify a signature for a given message. True is returned for a
                              valid signature otherwise false
    multisig-setup            Set up a multisig: quorum and all the participants (pubkeys in
                              hex)
    multisig-construct-msg    Add message to a multisig setup. Returns an unsigned
                              multisignature object
    multisig-sign             Sign a multisignature object passed via STDIN
    multisig-combine          Combine signatures of individually signed multisignature objects.
                              Pass them via STDIN
    multisig-verify           Verify a multisignature object passed via STDIN. Returns true or
                              false