Skip to content

Message Signing#

COLDCARD® can sign messages send to it via USB with the help of ckcc utility, sign messages provided via specially crafted file on SD card or Vdisk, and Mk4 can also sign messages sent to COLDCARD via NFC.

Signature format follows BIP-0137 specification. COLDCARD Mk3 and COLDCARD Mk4 up to version 5.1.0 used compressed P2PKH header byte for all script types. From Mk4 5.1.0 correct header byte is used for corresponding script type.

Verification#

(new in v5.1.0, requires Mk4)

Signed messages can be verified directly on the device. If signature file is on SD card or Virtual disk Advanced/Tools -> File Management -> Verify Sig File. In case signature file is detached signature of signed export (or any other file), COLDCARD can check if digest of file specified in the message matches contents of file. This requires signed file to be available on SD card or Vdisk. File size limit for signature files is approximately 10KB.

If signature file is imported via NFC Advance/Tools -> NFC Tools -> Verify Sig File. To cross-verify COLDCARD verification use Bitcoin Message Verifier as it supports multiple script types. Bitcoin core can only verify P2PKH.

Signing Text File#

Text file format#

First step is to choose a suitable text file to be signed. It must meet these requirements:

  • have file name extension TXT
  • be less than 500 bytes in size
  • filename cannot contain the string '-signed'

The file should contain a single line of text to be signed. If there is a second line (optional), it specifies the subkey derivation path for the key to be used for signing. Optionally, third line specifies desired address format (a.k.a script type). Default is P2PKH. P2SH-P2WPKH and P2WPKH are also supported.

The key subpath is optional and specifies a path from master key, such as m/48'/0'/0' or similar. If not provided, the m/44'/0'/0'/0/0 is used as a default.

Once a file has been selected, you'll be shown the message to be signed, and the subpath and address that will be used. You should press OK (✔) to proceed, and a new text file is created and saved with the signature added.

Message Restrictions#

There are restrictions on the message to be signed, including:

  • up to 240 characters long
  • ASCII only, and no control characters (ie. code points 32 to 127)
  • no more than 3 consecutive spaces
  • leading and trailing whitespace will be trimmed before signing
  • newline characters used in the file are stripped

These restrictions are also applied to messages signed using the USB protocol and NFC.

Example#

Here is a full example. Starting with this text file:

to-be-signed
m/23/23'/33

This sequence is shown on the COLDCARD:

msg-sig

This creates signme-signed.txt on the microSD card:

-----BEGIN BITCOIN SIGNED MESSAGE-----
to-be-signed
-----BEGIN BITCOIN SIGNATURE-----
1MDhJdtwjtGGbz3vQipUwtgjn5JPT2gWcT
H9JPn0tbPfDVRVC48YnAOwbYKTCFQ5hvimrBAPyRtuzjPxM+hbDCGk+CvtTt/BJrJZkgJi9/UAKyrnbyi0kBsM4=
-----END BITCOIN SIGNATURE-----

Verify file created in previous step in Advanced/Tools -> File Management -> Verify Sig File

msg-sig

Native Segwit Address#

to-be-signed-2
m/84'/0'/0'/0/0
p2wpkh

msg-sig

-----BEGIN BITCOIN SIGNED MESSAGE-----
to-be-signed-2
-----BEGIN BITCOIN SIGNATURE-----
bc1qcftdkqgllwwncn9qr8p9qkul6plr7ce6psrcjq
KBr0F/2cYgiemNnauJmgqyoohTRSe0GUXeDwH7ptcVgnQxHCtUgpYsoJ1IdXwxVKYB0VyEOqf5Umx0GCvd1FCyU=
-----END BITCOIN SIGNATURE-----

Wrapped Segwit Address#

to-be-signed-3
m/89'/0'/0'/0/0
p2sh-p2wpkh

msg-sig

-----BEGIN BITCOIN SIGNED MESSAGE-----
to-be-signed-3
-----BEGIN BITCOIN SIGNATURE-----
35AfXaJeytUdgcncuRTHAruBhcDQ6uVsUt
JFu0MgMCnsQ4UM/9MD4dIXElDQxYoZk+dEyp8St6DTYIBAVPxOb3XxLlwOMSgBhdCf0FD5ymF+0J6giOIXs4PVU=
-----END BITCOIN SIGNATURE-----

NFC signing#

Check NFC Tools for more info.

Signed Exports#

(new in v5.1.0, requires Mk4)

Most of SD card and Virtual disk exports are accompanied by detached signature file. If exported file name is coldcard-export.json signature file name will be coldcard-export.sig.

msg-sig

Message construction and signature file format#

  1. contents of the exported file are hashed with single SHA256 hash
  2. msg = hash from step 1. + two spaces + exported filename (basename)
  3. msg from step 2. is hashed again with Bitcoin msg hash "Bitcoin Signed Message:" + ser_compact_size(len(msg)) + msg
  4. detached signature file format:
-----BEGIN BITCOIN SIGNED MESSAGE-----
f1591bfb04a89f723e1f14eb01a6b2f6f507eb0967d0a5d7822b329b98018ae4  coldcard-export.json
-----BEGIN BITCOIN SIGNATURE-----
mtHSVByP9EYZmB26jASDdPVm19gvpecb5R
IFOvGVJrm31S0j+F4dVfQ5kbRKWKcmhmXIn/Lw8iIgaCG5QNZswjrN4X673R7jTZo1kvLmiD4hlIrbuLh/HqDuk=
-----END BITCOIN SIGNATURE-----

What is signed#

  1. Single sig address explorer exports. Signed by key corresponding to first (0th) address on the exported list.
  2. Specific single sig exports. Signed by key corresponding to external address at index zero of chosen application specific derivation m/<app_deriv>/0/0
    • Bitcoin Core
    • Electrum Wallet
    • Wasabi Wallet
    • Samourai Postmix
    • Samourai Premix
    • Descriptor
  3. Generic single sig exports. Signed by key that corresponds to address at derivation m/44'/<coin_type>'/0'/0/0 Lily Wallet Generic JSON Dump Summary
  4. BIP85 derived entropy exports. Signed by path that corresponds to specific BIP85 application.
  5. Paper wallet exports. Signed by key and address exported as paper wallet itself.

What is NOT signed#

Multisig exports and generic multisig xpub exports are not signed. It is not clear at this point whether to sign these exports with some generic single signature key (i.e. m/44'/<coin_type>'/0'/0/0) or with our portion (leg) of script. In both cases script type (address format) would not match as multisignature message signing is not standardized.

  1. Multisig exports
  2. Generic multisig exports