many updates
This commit is contained in:
parent
b1787f7b51
commit
4157641f09
|
@ -21,6 +21,7 @@
|
|||
* [Provision Computer](generated-documents/level-2/fixed-location/provisioner/provision-computer.md)
|
||||
* [Provision SD Card](generated-documents/level-2/fixed-location/provisioner/provision-sd-card.md)
|
||||
* [Provision AirgapOS](generated-documents/level-2/fixed-location/provisioner/provision-airgapos.md)
|
||||
* [Provision Root Entropy Ceremony SD Card](generated-documents/level-2/fixed-location/provisioner/provision-root-entropy-ceremony-sd-card.md)
|
||||
* [Copy Shardfile SD Card](generated-documents/level-2/fixed-location/provisioner/copy-shardfile-sd-card.md)
|
||||
* [Provision Air-Gapped Bundle](generated-documents/level-2/fixed-location/provisioner/air-gapped-bundle.md)
|
||||
* [Proposer](system-roles.md)
|
||||
|
|
|
@ -39,9 +39,9 @@ ceremonies/
|
|||
policies/
|
||||
spending-policy.json
|
||||
keychain/
|
||||
<key_id>/
|
||||
sig_1.asc
|
||||
sig_2.asc
|
||||
<key_fingerprint>/
|
||||
<last_16_digits_of_key_fingerprint>.asc
|
||||
<last_16_digits_of_key_fingerprint>.<last_16_digits_of_sigining_key>.asc.sig
|
||||
```
|
||||
|
||||
## Procedure: Setting up Repository
|
||||
|
|
|
@ -9,22 +9,18 @@ Setting up a PGP key pair is necessary for a number of different aspects of QVS.
|
|||
|
||||
* `keyfork mnemonic generate --size 256 > mnemonic.txt`
|
||||
|
||||
1. Write the mnemonic on a small piece of paper as you will need to enter the words in the next step. After entering the words, set the piece of paper on fire (that's why it should be small enough - to make burning it easy)
|
||||
|
||||
1. In a new terminal window start `keyfork` daemon with the mnemonic:
|
||||
1. Setting socket may not be necessary anymore (TODO test on Airgap):
|
||||
|
||||
* `export KEYFORKD_SOCKET_PATH=/tmp/keyforkd.socket`
|
||||
|
||||
* `keyfork recover mnemonic`
|
||||
1. Recover mnemonic to `keyforkd` and send process to background
|
||||
|
||||
* Enter the mnemonic as prompted
|
||||
* `keyfork recover mnemonic < mnemonic.txt`
|
||||
|
||||
* ctrl + z
|
||||
|
||||
* `bg`
|
||||
|
||||
* Burn the piece of paper which has the mnemonic written on it (HACK goes away when we fix keyfork)
|
||||
|
||||
1. Set expiration using the `KEYFORK_OPENPGP_EXPIRE` environment variable:
|
||||
|
||||
* `export KEYFORK_OPENPGP_EXPIRE=2y`
|
||||
|
@ -80,7 +76,7 @@ Setting up a PGP key pair is necessary for a number of different aspects of QVS.
|
|||
|
||||
1. Rename the private key file to contain the `key_id`:
|
||||
|
||||
* `mv priv.asc key_id.priv`
|
||||
* `mv priv.asc <key_id>.priv`
|
||||
|
||||
1. Export the public key:
|
||||
|
||||
|
|
|
@ -207,6 +207,16 @@ To construct an appropriate Tamper Proofing Station, the simplest setup consists
|
|||
|
||||
Pick a location for the station, and attach the LED light and the camera to the overhead camera mounting rig. Set up the camera so that when it's turned on, a 14" laptop is perfectly framed without having to zoom in or out if possible.
|
||||
|
||||
## High Visibility Storage
|
||||
|
||||
The purpose of high visibility storage is to provide a way to keep items which are used during a ceremony from risk of being swapped by one of the participants in the ceremony. As such, a high visibility storage should be a plastic container which is sealed, and which is only opened under the close supervision of a quorum of individuals.
|
||||
|
||||
Some examples include:
|
||||
|
||||
* Large glass jar
|
||||
|
||||
* Plastic bag
|
||||
|
||||
## Safe
|
||||
|
||||
Placing objects into a safe helps improve the security of objects, and introduces an additional layer of tamper evidence.
|
||||
|
|
|
@ -22,7 +22,7 @@ The approver is responsible for verifying a transaction proposed by a [proposer]
|
|||
|
||||
1. To sign the transaction payload and produce a detached signature use:
|
||||
|
||||
* `gpg --armor --output <approver.sig> --detach-sig <filename>`
|
||||
* `gpg --detach-sig <filename>`
|
||||
|
||||
1. Commit the detached signature alongside the tx
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
* Online machine
|
||||
|
||||
* [High Visibility Storage](TODO): plastic container or bag that's used to keep items while not in use in a visible location like the middle of a desk.
|
||||
|
||||
* [Operator PGP key pairs](../../key-types.md#operator-pgp-keypair)
|
||||
|
||||
{{ #include ../../../../operator-requirements.md:requirements }}
|
||||
|
@ -24,13 +26,15 @@
|
|||
|
||||
{{ #include ../../../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}}
|
||||
|
||||
1. Place all contents except for the laptop into High Visibility Storage
|
||||
|
||||
### Ceremony
|
||||
|
||||
1. Turn on online machine
|
||||
|
||||
1. Once booted, run `icepick workflow sol broadcast --nonce-address=<nonce_address>` command
|
||||
|
||||
- [ ] TODO find a place for the nonce_address in the ceremony repo
|
||||
- [ ] TODO find a place for the nonce_address in the ceremony repo or airgapOS
|
||||
|
||||
* Plug in "Transaction" SD card
|
||||
|
||||
|
@ -42,34 +46,133 @@
|
|||
|
||||
1. Boot the computer
|
||||
|
||||
1. Unplug the "AirgapOS" SD card
|
||||
1. Unplug the "AirgapOS" SD card and place it in High Visibility Storage
|
||||
|
||||
1. Plug in SD card labelled "Keychain"
|
||||
|
||||
* Load well known PGP keys of proposer and approver
|
||||
* `gpg --import <keyfile_name>`
|
||||
1. Use detached signatures of the keys on the SD cards to verify the pub certs. Each operator should verify that the each key in the Keychain has been signed by that operator's key.
|
||||
|
||||
1. Plug in a smart card with Operator PGP Key
|
||||
|
||||
1. Use the following script to check that a signature by the plugged in key exists for all the public certificates found on the Keychain
|
||||
- [ ] TODO move this to ceremony SD card or airgapOS
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
DIRECTORY="$1"
|
||||
|
||||
if ! compgen -G "$DIRECTORY/*.asc" > /dev/null; then
|
||||
echo "No .asc files found in the directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! gpg --card-status > /dev/null 2>&1; then
|
||||
echo "No smart card detected. Please insert a smart card."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
smart_card_id=$(gpg --card-status | grep sec | cut -d'/' -f2 | cut -d' ' -f1)
|
||||
|
||||
for asc_file in "$DIRECTORY"/*.asc; do
|
||||
gpg --import "$asc_file"
|
||||
done
|
||||
|
||||
for asc_file in "$DIRECTORY"/*.asc; do
|
||||
sig_exists="false"
|
||||
|
||||
for sig_file in "$DIRECTORY"/*.asc.sig; do
|
||||
sigfile_basename=$(basename "$sig_file" .asc.sig)
|
||||
ascfile_basename=$(basename "$asc_file" .asc)
|
||||
|
||||
if [[ "$sigfile_basename" != "$ascfile_basename" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
sig_key_id=$(gpg --verify "$sig_file" 2>&1 | grep 'Primary key fingerprint' | cut -d' ' -f4- | tr -d ' ')
|
||||
trimmed_key_id="${sig_key_id: -16}"
|
||||
|
||||
if [[ "$trimmed_key_id" == "$smart_card_id" ]]; then
|
||||
sig_exists="true"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$sig_exists" == "false" ]]; then
|
||||
printf "\nWARNING: Signature for %s by operator key %s does not exist\n" "$asc_file" "$smart_card_id"
|
||||
fi
|
||||
done
|
||||
|
||||
```
|
||||
|
||||
1. Ensure that the script doesn't output any "WARNING" messages to the console. If it does, abort the ceremony and initiate incident response.
|
||||
|
||||
1. Use detached signatures of the keys on the SD cards to verify the pub certs
|
||||
|
||||
- [ ] write bash script that for each pub cert, looks for 2 detached sigs made by two other certs
|
||||
|
||||
1. Unplug the "Keychain" SD card
|
||||
1. Unplug the "Keychain" SD card and place it in High Visibility Storage
|
||||
|
||||
1. Insert SD card labelled "Shardfile"
|
||||
|
||||
1. [ ] in root entropy ceremony add step to write an autorun.sh script to shardfile sd card that runs `keyfork recover shard --daemon`
|
||||
1. If no prompt appears, run the command:
|
||||
|
||||
* Follow on screen prompts
|
||||
* `keyfork recover shard --daemon`
|
||||
|
||||
1. Unplug SD card labelled "Shardfile"
|
||||
1. Follow on screen prompts
|
||||
|
||||
1. Plug in the "Transaction" SD card
|
||||
1. Unplug SD card labelled "Shardfile" and place it in High Visibility Storage
|
||||
|
||||
1. Retrieve the "Transaction" SD card from High Visibility Storage and plug in the "Transaction" SD card
|
||||
|
||||
1. For each transaction, verify that the signature is made by trusted keys that are loaded in the gpg keyring:
|
||||
- [ ] TODO: move this to ceremony SD card
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
* `gpg --verify <detached_signature>`
|
||||
DIRECTORY=$1
|
||||
|
||||
declare -a key_ids
|
||||
|
||||
while IFS= read -r line; do
|
||||
key_id=$(echo "$line" | awk -F: '/^pub/{print $5}')
|
||||
if [[ -n "$key_id" ]]; then
|
||||
key_ids+=("$key_id")
|
||||
fi
|
||||
done < <(gpg --list-keys --with-colons)
|
||||
|
||||
check_key_id() {
|
||||
local search_key_id="$1"
|
||||
for id in "${key_ids[@]}"; do
|
||||
if [[ "$id" == "$search_key_id" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
for tx in "$DIRECTORY"/*.json; do
|
||||
basename=$(basename "$tx" .json)
|
||||
number_of_sigs=0
|
||||
tx_sig="$DIRECTORY/$basename.json.sig"
|
||||
|
||||
if [[ ! -f "$tx_sig" ]]; then
|
||||
echo "WARNING: No signature file found for transaction $tx."
|
||||
continue
|
||||
fi
|
||||
|
||||
sig_key_id=$(gpg --verify "$tx_sig" 2>&1 | grep 'Primary key fingerprint' | cut -d' ' -f4- | tr -d ' ')
|
||||
trimmed_key_id="${sig_key_id: -16}"
|
||||
|
||||
if check_key_id "$trimmed_key_id"; then
|
||||
((number_of_sigs++))
|
||||
else
|
||||
echo "Key ID $trimmed_key_id not found in key_ids array."
|
||||
fi
|
||||
|
||||
if (( number_of_sigs < 2 )); then
|
||||
echo "WARNING: Insufficient signatures ($number_of_sigs) for transaction $tx."
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
- [ ] todo write a script for this
|
||||
|
||||
1. Run the `icepick` command with the transaction payload
|
||||
|
||||
|
@ -77,7 +180,7 @@
|
|||
|
||||
* Follow on screen prompts
|
||||
|
||||
1. Unplug the "Transaction" SD card
|
||||
1. Unplug the "Transaction" SD card and place it in High Visibility Storage
|
||||
|
||||
### Broadcast Transaction
|
||||
|
||||
|
|
|
@ -8,12 +8,11 @@ This is a ceremony for generating root entropy.
|
|||
|
||||
{{ #include ../../operator-requirements.md:requirements }}
|
||||
|
||||
* Each member needs to bring their:
|
||||
* Minimum of 2 fresh SD cards
|
||||
|
||||
* Ceremony Notes
|
||||
* [Ceremony SD Card](../provisioner/provision-root-entropy-ceremony-sd-card.md)
|
||||
|
||||
* Ceremony SD Card
|
||||
- [ ] TODO explain what this is
|
||||
* [High Visibility Storage](TODO): plastic container or bag that's used to keep items while not in use in a visible location like the middle of a desk.
|
||||
|
||||
## Procedure
|
||||
|
||||
|
@ -21,24 +20,46 @@ This is a ceremony for generating root entropy.
|
|||
|
||||
1. Lock access to the location - there should be no inflow or outflow of people during the ceremony
|
||||
|
||||
1. Retrieve sealed laptop and polaroid from locked storage
|
||||
1. Retrieve Air-Gapped Bundle from locked storage
|
||||
|
||||
### Unsealing Tamper Proofing
|
||||
|
||||
{{ #include ../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-unsealing}}
|
||||
|
||||
1. Place all materials except for the laptop into High Visibility Storage
|
||||
|
||||
### Generating Entropy
|
||||
|
||||
1. Boot AirgapOS on the airgapped machine
|
||||
1. Retrieve AirgapOS SD card from High Visibility Storage and plug it into air-gapped laptop
|
||||
|
||||
1. Verify the hash of the AirgapOS version once it's booted
|
||||
1. Turn on the machine
|
||||
|
||||
1. Run `ceremony.sh`
|
||||
1. Once booted, remove the AirgapOS SD card and place it into High Visibility Storage
|
||||
|
||||
1. Plug in the Ceremony SD card
|
||||
|
||||
1. Run `ceremony.sh` from the SD card
|
||||
|
||||
1. Button mash to ensure adequate entropy on the OS
|
||||
|
||||
1. Back up the `shardfile`, and `pub.asc` to at least 2 separate SD cards
|
||||
1. Back up the `shardfile` to any desired number of SD cards, and label each "Shardfile <date>"
|
||||
|
||||
1. Optionally write an `autorun.sh` file to the Shardfile SD card containing the following command:
|
||||
|
||||
* `keyfork recover shard --daemon`
|
||||
|
||||
1. If an OpenPGP certificate was derived, store the public key on a SD card, separate from the shardfiles
|
||||
|
||||
### Finalizing Ceremony
|
||||
|
||||
1. Seal the airgapped bundle (TODO)
|
||||
1. Gather all the original items that were in the air-gapped bundle:
|
||||
|
||||
* Air-gapped computer
|
||||
|
||||
* AirgapOS SD card
|
||||
|
||||
* Shardfile SD card
|
||||
|
||||
* Keychain SD card
|
||||
|
||||
{{ #include ../../../../component-documents/tamper-evidence-methods.md:vsbwf-procedure-sealing}}
|
|
@ -26,7 +26,7 @@ The proposer must combine these values into a single message, which can be a sim
|
|||
|
||||
## Procedure
|
||||
|
||||
1. Define a new file "<date:time>-<currency>.tx.json", for example "16:40-PYTH-SPL.tx.json"
|
||||
1. Define a new file `workflow_inputs_<num>.json`, for example `workflow_inputs_1.json`
|
||||
|
||||
1. Create a new directory in the `ceremonies` repository for the date on which the ceremony for the transaction will take place if it doesn't already exist, for example `2024-01-01/`
|
||||
|
||||
|
@ -54,7 +54,7 @@ The proposer must combine these values into a single message, which can be a sim
|
|||
|
||||
1. Sign the data in the CLI using `gpg` or another OpenPGP implementation:
|
||||
|
||||
* `gpg --clearsign <file>`
|
||||
* `gpg --detach-sig <file>`
|
||||
|
||||
1. Notify relevant individuals that there are new transactions queued up, and that a ceremony should be scheduled. This can be automated in the future so that when a commit is made or PR opened, others are notified, for example using a incident management tool.
|
||||
|
||||
|
|
|
@ -2,4 +2,23 @@
|
|||
|
||||
There should be multiple SD cards containing the shardfile data. Shardfile data is produced during a [Root Entropy](../operator/hybrid-key-provisioning.md) derivation ceremony.
|
||||
|
||||
Label the SD card: "Shardfile <date>"
|
||||
## Requirements
|
||||
|
||||
* Existing Shardfile SD card
|
||||
|
||||
* Fresh SD card(s)
|
||||
|
||||
## Procedure
|
||||
|
||||
1. Get the shardfile content from an existing Shardfile SD card or ceremony repository
|
||||
|
||||
1. Plug in a fresh SD card
|
||||
|
||||
1. Copy the shardfile to the new SD card
|
||||
|
||||
1. Label the SD card: "Shardfile <date>"
|
||||
|
||||
1. Optionally write an `autorun.sh` file to the Shardfile SD card containing the following command:
|
||||
|
||||
* `keyfork recover shard --daemon`
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
# Provision Root Entropy Ceremony SD Card
|
||||
|
||||
1. Plug in a fresh formatted SD card into the computer
|
||||
|
||||
1. Create a directory called `public_certificates` on the SD card
|
||||
|
||||
1. Copy the desired OpenPGP public certificates you wish to shard to during the ceremony into the `public_certificates` directory on the SD card. The number of public certificates in this directory corresponds to the `N` value in a `M of N` quorum.
|
||||
|
||||
1. Write the following script to a file called `ceremony.sh`
|
||||
|
||||
* `<threshold_value>` should be replaced with the desired `M` value in a `M of N` quorum
|
||||
|
||||
* If you would like to generate an OpenPGP public certificate, add `--output-cert /media/cert` and `--user-id <name>` to the command
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
|
||||
script_dir="$(dirname "$(realpath "$0")")"
|
||||
|
||||
read -p "Provide the path to PGP certificates which will be used for the ceremony: " relative_path
|
||||
|
||||
directory_path="$script_dir/$relative_path"
|
||||
|
||||
if [ ! -d "$directory_path" ]; then
|
||||
echo "Directory does not exist. Please enter a valid directory path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in "$directory_path"/*; do
|
||||
if [ -f "$file" ]; then
|
||||
echo "Processing file: $file"
|
||||
gpg --import --import-options import-show $file
|
||||
fi
|
||||
done
|
||||
|
||||
read -p "Do the PGP key IDs match what you expect? (y/n): " matches_expectation
|
||||
|
||||
if [ $matches_expectation != "y" ]; then
|
||||
echo "Ceasing ceremony as PGP key IDs don't match"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
keyfork bottoms-up --threshold <threshold_value> --output-shardfile /media/shardfile /media/public-certificates/
|
||||
```
|
||||
|
||||
1. Write the `ceremony.sh` script to the SD card
|
||||
|
||||
1. Burn the SD card contents to the SD card using `sdtool`
|
||||
|
||||
{{ #include ../../../../sdtool-instructions.md:steps }}
|
|
@ -19,11 +19,21 @@ This tool is also available via [stagex](https://registry.hub.docker.com/r/stage
|
|||
* To get container hash: `docker inspect --format='{{json .RepoDigests}}' stagex/sdtool`
|
||||
* Check the [signatures dir](https://codeberg.org/stagex/stagex/src/branch/main/signatures/stagex) in stagex project for latest signed hashes
|
||||
|
||||
1. `./sdtool /dev/mmcblk permlock`
|
||||
1. Use `lsblk` to figure out the SD card device name
|
||||
|
||||
* Note: the device will not mount as a proper block device on QubesOS so a different OS has to be used where the device appears as /dev/mmcblk<num>
|
||||
|
||||
1. `./sdtool /dev/<device_name> permlock`
|
||||
|
||||
1. Test that the card can't be written to:
|
||||
|
||||
* `dd if=out/airgap.iso of=/dev/sdb bs=1M conv=sync status=progress`
|
||||
* Create a test file:
|
||||
|
||||
* `echo "test" > test.txt`
|
||||
|
||||
* Try writing the file to the SD card
|
||||
|
||||
* `dd if=./test.txt of=/dev/<device_name> bs=1M conv=sync status=progress`
|
||||
|
||||
// ANCHOR_END: steps
|
||||
/* ANCHOR_END: all */
|
Loading…
Reference in New Issue