Blockstream / Blockstream/Jade
[Feature Request] Add detached signature for firmware manifests
- Dominant language
- C
- Stars
- 496
- Forks
- 127
- PR merge metrics
- No merged PRs in 30d
Description
# [Feature Request] Add detached signature for firmware manifests
## Summary
It would be useful to provide a detached cryptographic signature for the firmware metadata manifests published at:
* `https://jadefw.blockstream.com/bin/jade/index.json`
* `https://jadefw.blockstream.com/bin/jade1.1/index.json`
* `https://jadefw.blockstream.com/bin/jade2.0/index.json`
For example:
```text
index.json
index.json.asc
```
signed by a documented Blockstream/Jade firmware release key.
I think signing the manifest is probably simpler and more scalable than providing a separate PGP signature for every firmware binary, because `index.json` already contains the hashes needed to verify the individual firmware files.
## Current verification
I recently manually verified Jade 2.0 firmware downloaded from:
`https://jadefw.blockstream.com/upgrade/download.html`
For example, for firmware `1.0.41` the ZIP contains:
```text
1.0.41_ble_1445888_fw.bin
1.0.41_ble_1445888_fw.bin.hash
1.0.41_noradio_1183744_fw.bin
1.0.41_noradio_1183744_fw.bin.hash
```
The downloaded compressed binary can be checked directly against the `cmphash` from `index.json`:
```bash
BIN_FILE="1.0.41_ble_1445888_fw.bin"
sha256sum "$BIN_FILE"
```
The final uncompressed firmware can also be checked against the published `fwhash` and the accompanying `.hash` file:
```bash
BIN_FILE="1.0.41_ble_1445888_fw.bin"
cp "$BIN_FILE" tmp.fw.gz
pigz -z -d tmp.fw.gz
sha256sum tmp.fw
rm tmp.fw
cat "$BIN_FILE".hash
```
In my case both the BLE and no-radio builds matched the values published in:
`https://jadefw.blockstream.com/bin/jade2.0/index.json`
So the existing hash verification works well.
## Motivation
The hashes provide a good way to verify that the firmware downloaded by the user is exactly the firmware represented by the metadata.
However, the firmware binaries and their expected hashes are obtained from the same Blockstream firmware infrastructure.
For example, a user currently effectively verifies:
```text
downloaded .bin
│
├── SHA256 ──> cmphash in index.json
│
└── decompress
│
└── SHA256 ──> fwhash in index.json / .hash
```
A detached signature over `index.json` would add another verification layer:
```text
Trusted Jade release public key
│
│ signature verification
▼
index.json
/ \
cmphash fwhash
│ │
▼ ▼
compressed uncompressed
firmware firmware
```
A user could first authenticate the manifest:
```bash
gpg --verify index.json.asc index.json
```
and then use the authenticated `cmphash` / `fwhash` values to verify the downloaded firmware.
## Why sign the manifest instead of every `.bin`?
Signing `index.json` seems like the smallest change because the manifest already contains:
```text
filename
version
config
fwsize
cmphash
fwhash
```
One detached signature would therefore authenticate the hashes and metadata for all firmware entries in that manifest.
It would avoid needing files such as:
```text
1.0.41_ble_1445888_fw.bin.asc
1.0.41_noradio_1183744_fw.bin.asc
...
```
for every build.
The existing firmware download format would not need to change.
Something like this could simply be added alongside each manifest:
```text
/bin/jade/index.json
/bin/jade/index.json.asc
/bin/jade1.1/index.json
/bin/jade1.1/index.json.asc
/bin/jade2.0/index.json
/bin/jade2.0/index.json.asc
```
## Public key distribution
For this to provide meaningful independent authentication, the signing key fingerprint should also be documented somewhere outside the firmware server itself.
For example:
* Jade GitHub repository
* `FWUPDATE.md`
* Blockstream Jade documentation
* other official Blockstream channels
Ideally this would be a dedicated release-signing key rather than requiring the private key used internally by Jade to authenticate firmware on official devices.
## Relationship with Jade's existing firmware signature
I understand that official Blockstream Jade units already verify that firmware has been signed by Blockstream before accepting/running it.
This proposal is not intended to replace that mechanism.
The existing firmware signature provides authentication at the device level:
```text
Jade → verifies firmware
```
The proposed detached manifest signature would additionally allow:
```text
User → verifies firmware release metadata
```
before uploading the firmware to Jade.
This would complement the existing firmware signing and reproducible-build verification.
## Proposed minimal implementation
1. Create/use a documented Jade firmware release-signing OpenPGP key.
2. Generate a detached signature whenever an `index.json` manifest is updated:
```bash
gpg --armor --detach-sign index.json
```
3. Publish `index.json.asc` next to each existing `index.json`.
4. Publish and document the signing-key fingerprint in the Jade repository and documentation.
5. Add a short optional verification example to `FWUPDATE.md`:
```bash
gpg --verify index.json.asc index.json
sha256sum
```
The second result can then be compared with the now-authenticated `cmphash`.
This seems like a relatively small addition while giving users who manually verify firmware an additional independent authenticity check.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with FWUPDATE.md and the three published index.json manifests, then trace how firmware metadata is released. Confirm the signing-key, publication, and documentation requirements; done means each manifest has a verifiable detached signature and the key fingerprint and verification steps are documented.
Written by the indexing model from the issue text.
Assessment
- Domain
- documentation, embedded-iot, release, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100