Message Signing#
COLDCARD® can sign messages sent to it via USB (with the help of the ckcc
utility), messages provided via a specially crafted file on the SD card or Virtual Disk, or messages sent to the COLDCARD via NFC. In addition, the Q can sign messages via QR & BBQr codes.
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#
Signed messages can be verified directly on the device. If the signature file is on the SD card or Virtual Disk, go to: Advanced/Tools > File Management > Verify Sig File
.
In case the signature file is a detached signature of a signed export (or any other file), COLDCARD can check if the digest of the file specified in the message matches the contents of the file. This requires the signed file to be available on the SD card or Vdisk. The size limit for signature files is approximately 10KB.
Signed messages can now be verified by scanning the whole RFC armored message with the QR scanner. It is necessary to encode signed message as BBQr.
A signature file can also be imported via NFC by heading to: 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.
QR/BBQr Message Signing#
The COLDCARD Q can sign a message encoded as a JSON object, when displayed as a QR or BBQr. Scan the QR or BBQr with the Q's built-in scanner to begin message signing.
The JSON format for the message is:
{"msg": "<required msg>", "subpath": "<optional sp>", "addr_fmt": "<optional af>"}
Steps for QR/BBQr Message Signing
-
Scan a JSON object encoded as a QR or BBQr.
-
Below is an example using BBQr:
-
Or scan Simple QR below:
-
-
Next is by the classic authorization UX where one should check the address and message:
-
After all is verified and confirmed, choose a way to export signature:
-
An additional prompt is shown if QR export is chosen:
-
It is possible to export a signature as a simple text QR:
-
Or a full RFC armored msg as BBQr:
-
Signing Message From Text#
The COLDCARD Q can sign messages from simple text scanned in a QR code, or Secure Notes & Passwords from within the device.
Steps for Signing a Message From Text
-
Select a Secure Note or Password stored on the COLDCARD, or scan a QR containing the simple text to be singed.
-
Sign Secure Note text
-
Sign Password text note
-
Sign simple scanned text (from QR)
-
-
On the next few screens the user is queried to build the derivation path for the address to sign with. First, address format:
-
Next, choose an account number or press ENTER for
0
. -
Is this address change or not?
-
Now provide the address index.
-
Followed by the classic sign message authorization UI.
QR Signing With Sparrow#
- Select
Addresses
in left column of your wallet. - Choose address for which to sign message, right-click on it and select
Sign/Verify Message
. - Input message to be signed (address is already filled from previous selection).
- Choose
Sign by QR
in bottom left part of open Sign/Verify Message window. - Scan presented QR with COLDCARD Q, verify address & message on screen and confirm by pressing ENTER.
- Press QR key to export as QR.
- Press ENTER to only export signature QR, QR is now displayed on COLDCARD screen.
- Choose
Scan QR
in Sparrow open window (button in the bottom right corner) where QR is displayed. - Use your PC camera to scan the QR from the COLDCARD display.
- Now signature field is filled in the open
Sign/Verify Message
window and it verifies OK!
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 or JSON (new in v5.4.1 & v1.3.1Q, requires Mk4)
- 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, the third line specifies the desired address format (a.k.a script type). Default
is P2PKH
, but P2SH-P2WPKH
and P2WPKH
are also supported.
If the file contains a JSON object, it must contain the msg
field. The subpath
and addr_fmt
fields are optional.
{"msg":"this address belongs to me","subpath":"m/84h/0h/0h/0/120"}
The key derivation path is optional and specifies a path from master key, such as
m/48h/0h/0h
or similar. If not provided, the m/44h/0h/0h/0/0
is used as default for P2PKH
,
m/49h/0h/0h/0/0
for P2SH-P2WPKH
, and m/84h/0h/0h/0/0
for P2WPKH
. BIP-44 coin type index
is 1
if on testnet chain. Before Mk4 5.2.3
if key derivation path was not provided, default
was m
.
To select a file, navigate to: Advanced/Tools > File Management > Sign Text File
.
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.
Sign Text File Example
Sign Text File Example#
Here is a full example. Starting with this text file:
to-be-signed
m/23/23h/33
or JSON:
{"msg":"to-be-signed","subpath":"m/23/23h/33"}
This sequence is shown on the COLDCARD:
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
Native Segwit Address#
to-be-signed-2
m/84h/0h/0h/0/0
p2wpkh
same as
to-be-signed-2
p2wpkh
or JSON:
{"msg":"to-be-signed-2","addr_fmt":"p2wpkh"}
-----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/49h/0h/0h/0/0
p2sh-p2wpkh
or JSON:
{"msg":"to-be-signed-3","addr_fmt":"p2sh-p2wpkh", "subpath": "m/49h/0h/0h/0/0"}
-----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.
Signing Messages From Known Address#
(new in v5.4.1 & v1.3.1Q, requires Mk4)
The COLDCARD allows you to sign a message from a positive address ownership check, or from a custom address selected in Address Explorer.
Steps for Signing a Message From a Known Address
-
Begin by selecting an address to sign with, either scan an address for verification or select an address in the Address Explorer.
-
For an address scanned with the QR scanner, press 0 after successful ownership check to use it for signing.
-
For an address selected in the Address Explorer, press 0 after
Custom Path
address is shown on theShowing Single Address
screen.
-
-
Next, input a message to be signed (can be scanned on Q).
-
After this step, the classic signing authorization UI is provided.
Signed Exports#
Most of the SD card and Virtual Disk exports are accompanied by a detached signature file.
If the exported file name is coldcard-export.json
, the signature file name will be coldcard-export.sig
.
An export format can be chosen in: Advanced/Tools > Export Wallet
.
Message Construction and Signature File Format#
- Contents of the exported file are hashed with single SHA256 hash
msg = hash from step 1. + two spaces + exported filename (basename)
msg
from step 2 is hashed again with Bitcoin msg hash"Bitcoin Signed Message:" + ser_compact_size(len(msg)) + msg
- 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#
- Single sig address explorer exports: Signed by the key corresponding to the first (0th) address on the exported list.
- Specific single sig exports: Signed by the key corresponding to the 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
- 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
- BIP85 derived entropy exports: Signed by path that corresponds to specific BIP85 application.
- 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 the script. In both cases the script type (address format) would not match as multisignature
message signing is not standardized.
- Multisig exports
- Generic multisig exports