Skip to content

Usage Tutorial

wizardofhoms edited this page May 19, 2023 · 10 revisions

Summary

This page requires the following things:

  • The vault AppVM configured according to the installation instructions
  • A SDCard (or a USB device) to be used as a hush device.
  • (Optional) another USB device to be used as backup medium.

Note that all commands below do not make use of the --verbose/-v command flag, since for some commands, it would produce too much output. This flag can be used the first time you use a command, if you are interested in all the steps that are taken (the code makes an extensive use of verbose logging), but for most practical purposes you won't need it.

Preparing devices

Hush

First we need to setup the SDCard to be used as a hush device. The following command will:

  • Wipe all data on the device
  • Create partitions according to either defaults or values specified by command flags.
  • Encrypt the filesystem of one partition with LUKS.
  • Write a udev rule into a file that risks will automatically link to its equivalent in /etc/udev/rules.d/
  • Copy the risks CLI and its completions into the hush device (under .risks/), along with a small install scriptlet. This is done for maximum portability of the hush device itself: if used on another computer, you can quickly install the risks tools onto the machine, and use the device as normal.

First attach the SDCard to your vault, with one of these methods:

  • Use the devices GUI in the Qubes systray.
  • Use the qvm-block attach <device> command in a dom0 terminal.
  • If the risk dom0 CLI is installed, use risk hush attach.

The following shows the formatting process of a new device:

user@vault $ risks hush format /dev/xvdi
risks  .  Overwriting and partitioning SDCARD
1997537280 bytes (2.0 GB, 1.9 GiB) copied, 187 s, 10.7 MB/s
dd: error writing '/dev/xvdi': No space left on device
1909+0 records in
1908+0 records out
2000683008 bytes (2.0 GB, 1.9 GiB) copied, 281.76 s, 7.1 MB/s
risks  .  Creating partitions
risks  .  Creating LUKS filesystem
Enter passphrase for /dev/xvdi2: 
Verify passphrase: 
Key slot 0 created.
Command successful.
Enter passphrase for /dev/xvdi2: 
risks  .  Making filesytem and setting up high-level encryption (fscrypt)
risks  .  Setting Udev rules for hush partition 
risks  .  Copying risks scripts onto the hush partition
risks  .  Setting Udev rules for hush partition 
risks  .  No link to hush udev rules detected, setting it persistent and for this session
risks (*) Successfully formatted and prepared SDcard as hush device

Following this, you must detach the SDCard from the vault qube, and attach it again, so that the newly created udev rules takes effect on the mapping mechanism.

Backup (optional, recommended)

Next we can do the same process for another device used as a backup medium. The command structure is the same, and the steps taken are also similar:

  • Wipe all data on the device
  • Encrypt the filesystem the partition with LUKS.
user@vault $ risks backup format /dev/xvdj
risks  .  Formatting and encrypting backup drive
15375269888 bytes (15 GB, 14 GiB) copied, 1639 s, 9.4 MB/s 
dd: error writing '/dev/xvdj': No space left on device
14664+0 records in
14663+0 records out
15376000000 bytes (15 GB, 14 GiB) copied, 1688.51 s, 9.1 MB/s
risks  .  Setting up LUKS on drive
Enter passphrase for /dev/xvdj: 
Verify passphrase: 
Key slot 0 created.
Command successful.
Enter passphrase for /dev/xvdj: 
risks  .  Making ext4 filesystem on LUKS mapper
risks  .  Enabling filesystem encryption and setting up fscrypt
risks  .  Setting up fscrypt in backup mount point (/tmp/pendrive)
risks  .  Unmounting backup pendrive
risks  .  Backup device is umounted and closed
risks (*) Done formatting and encrypting backup drive
risks (*) Use 'risks backup mount' to get read-write access

Creating an identity

Now that our devices are ready to store identity secrets and/or their data, we can create a new identity. Note that the process takes a few moments (not hours), and that you should not "panic" if things look a bit slow.

The command to create identity takes 3 parameters:

  • A "full name" to be used as the full name for the GPG key UID. This needs to be quoted if containing spaces. You can also use a single nym instead. This name is also used to to compute/resolve various paths for the identity, so if you choose a full name such as "John Doe", risks will use this name as is in the GPG key, but will modify it to be "John_Doe" when using it in the code and for file resolution. As well, when opening the identity, you will need to use risks open identity John_Doe.
  • An address email to use for the GPG UID.
  • An expiry date for the GPG subkeys. This can be a human-readable format, such as "1 year", "5 months", or any other GPG-compliant format. Note that you also need to quote the argument if it contains spaces. If you don't want the subkeys to expire, use "0".

We first reattach the hush device' encrypted partition (eg. dom0:sda2) to the vault, and mount it in the vault:

user@vault $ risks hush mount 
Enter passphrase for /dev/hush: 

risks (*) SDCARD has been mounted read-only. To give write permissions, use:
risks (*) risks hush rw

The following command creates a new identity. We don't use the --backup flag to immediately back the identity, as we will show backup commands in a later section.

user@vault $ risks identity create PrimeWizard primewizard@proton.me "1 year"
 risks  .  Starting new identity generation process
 risks [W] Do not unplug hush and backup devices during the process
 risks  .  Using PrimeWizard as identity name
 risks  .  Using primewizard@proton.me as email
   gpg  .  Setting up RAMDisk and GPG backend
   gpg  .  Generating GPG keys
   gpg [W] GPG passphrase copied to clipboard with one-time use only
   gpg  >  Paste it in the coming GPG prompt when creating builtin tombs
coffin  .  Creating and setting encrypted identity directory
  hush  .  Mounting hush device with read-write permissions
  hush  .  Sdcard already mounted
coffin  .  Creating and testing GPG coffin container
   gpg  .  Cleaning and backing keyring privates
   gpg  .  Identity 'PrimeWizard' is now ACTIVE
   ssh  .  Generating SSH keypair and multi-key ssh-agent script
  pass  .  Initializing password-store
  mgmt  .  Creating management tomb
signal  .  Creating Signal messenger tomb

 risks (*) Identity generation complete.

Note that at some point in the process above (at gpg . Cleaning and backing keyring) you will be prompted by GPG to enter the passphrase for the private key. As you can see in the output above, the GPG passphrase has been copied into the clipboard with one-time use, to this effect.

A few other things:

  • A mgmt tomb is created by default, to store various stuff that you might want to store for this identity. The kv command (managing a primary key-value store) stores its keys into it.

You can also generate a burner identity: this will only generate the GPG keys and a password-store tomb. Various combinations are possible:

risks identity create BurningMan --burner           # Only generate GPG keys and passwor-store.
risks identity create --burner                      # Randomly generate a name (note it !), with no mail address on GPG key.
risks identity create --burner --mail proton.me     # Random name, and use <random_name@proton.me> as GPG key mail.

Creating new tombs

We can now create new tombs for this identity. The latter is already active (because the GPG keyring is mounted and available for use). Here we create a Data tomb, with size 20M. Note that we still don't use the --verbose flag which, if used, would show the full tomb command output. Note in the prompt below, the active identity.

user@vault [ PrimeWizard ] $ risks tomb create Data 20
risks  .  Creating tomb Data with size 20M
risks [W] GPG passphrase copied to clipboard with one-time use only
risks  >  Copy it in the coming GPG prompt when creating the tomb.
risks  .  Done creating tomb.

What our filesystem looks like

At this point we will pause a little, and show how the various files of this identity look like on the filesystem.

We start with the hush device, which contains the coffin-key file and tomb-key files for our tombs (5 right now: GPG, SSH, Pass, mgmt and Data). Here is what the ~/.hush/ directory looks like:

user@vault [ PrimeWizard ] $ ls -l ~/.hush 
total 28K
-rw------- 1 user user 976 Oct 19 00:22 botwicizo
-rw------- 1 user user 976 Oct 19 00:33 jisdugeda
-rw------- 1 user user 971 Oct 19 00:22 midjizova
-rw------- 1 user user 976 Oct 19 00:22 totmexahu
-rw-r--r-- 1 user user  64 Oct 19 00:21 vedjoyixi
-rw------- 1 user user 976 Oct 19 00:22 yilruvoxi

None of those files have name matching our tombs and coffin keys. This is because all of these names are the encrypted original filename, thanks to the spectre password generator. This is so that there is no way for an external watcher to deduce which file belongs to which identity.

We continue with the ~/.graveyard directory. Note that we can read the raw files and directories (even if they are encrypted), since the identity is active, and thus its graveyard directory is unlocked.

.graveyard
├── cazletobo                   # The graveyard for the PrimeWizard identity
│   ├── balwowesa.tomb          # All tomb files for this identity
│   ├── kobwuxifi.tomb
│   ├── korkayefe.tomb
│   ├── tildiqure.tomb
│   ├── wuldokihe.tomb
│   └── xaymacigo.tomb
└── witjerize                   # The GPG coffin file for PrimeWizard.

Now, we close the identity, to check what the same graveyard looks like:

user@vault [ PrimeWizard ] $ risks identity close
risks  .  Closing Signal tomb ...
risks  .  Closing PASS tomb ...
risks  .  Closing SSH tomb ...
risks  .  Closing Management tomb ...
risks  .  Closing GPG coffin ...
risks  .  Identity 'PrimeWizard' is now INACTIVE

user@vault $ tree ~/.graveyard
.graveyard
├── cazletobo
│   ├── 1PhBmhduXC0R720hjqh-T00q2iIhRC6C2SZy8M-Sd7k2zhrnnDoiOA
│   ├── JMmZhoiXzng61LkiRpdhaQx9Ji4cZqXtCWuw6UgPrjCqmzrH9Qvhhg
│   ├── NMFnJlH4Wewa31_YA4tnKFvLTjXqDCqk1rqkVWYeV68ZMcqadtIi4w
│   ├── WvcegtCBiBGdWAQgESBoMg47_Q5PIKw1xjp9n3uQj2q_bIp2v4lQTQ
│   ├── io30pHSiS2gmUNYOiiFJYFzg7YiT9WpH5U3BUFwOJKEF2f0NudmyqA
│   └── wIX57ygNm4axga5BrULywQyNuXzQ8aieR3B2J6JKRxv_N0_lO-GzvQ
└── witjerize

The files in the identity graveyard are now "double-encrypted", since fscrypt added another layer of encryption on these files. fscrypt unlocks this directory when the identity is opened, and locks it when the identity is closed. It does the same thing when accessing an identity's backup directory, as we shall see below.

Opening/closing tombs

We first open the identity again, here only opening the GPG coffin, and no tombs:

user@vault [ PrimeWizard ] $ risks gpg open PrimeWizard 
risks  .  Opening coffin and mounting GPG keyring
risks  .  Identity 'PrimeWizard' is now ACTIVE

Below is the output of the commands when opening the Data tomb:

user@vault [ PrimeWizard ] $ risks tomb open Data
risks [W] GPG passphrase copied to clipboard with one-time use only
tomb  .  Commanded to open tomb /home/user/.graveyard/cazletobo/korkayefe.tomb
tomb [W] File is not yet a tomb: /home/user/.graveyard/cazletobo/korkayefe.tomb
tomb  .  Valid tomb file found: /home/user/.graveyard/cazletobo/korkayefe.tomb
tomb  .  Key is valid.
tomb (*) Opening korkayefe on /home/user/.tomb/Data
tomb  .  This tomb is a valid LUKS encrypted device.
tomb  .  Cipher is "aes" mode "xts-plain64" hash "sha512"
DM-UUID for device tomb.korkayefe.79e341886699892213ceadaae37f5390129b8f693154780e2d82ebaaf5d5a8e5.loop1 was truncated.
tomb (*) Success unlocking tomb korkayefe
tomb  .  Filesystem detected: ext4
tomb  .  Checking filesystem via /dev/loop1
fsck from util-linux 2.36.1
korkayefe: clean, 11/4608 files, 1911/18432 blocks
tomb (*) Success opening korkayefe.tomb on /home/user/.tomb/Data
touch: cannot touch '/home/user/.hush/jisdugeda': Read-only file system
touch: cannot touch '/home/user/.hush/jisdugeda': Read-only file system

And, closing it:

user@vault [ PrimeWizard ] $ risks tomb close Data
tomb  .  Closing tomb [korkayefe] mounted on /home/user/.tomb/Data
tomb (*) Tomb [korkayefe] closed: your bones will rest in peace.

Using GPG

In order to use our GPG keys we must often use the associated passphrase. Since all passphrases are managed with spectre, no passwords are ever saved on the system (except password-store ones). So the GPG passphrase is generated from several parameters, of which the identity name and a master password, and in fact you don't even need to open the identity to produce its GPG passphrase, even though it is not useful in itself and alone.

The following command gives the GPG passphrase:

user@vault [ PrimeWizard ] $ risks gpg pass 
risks  .  The passphrase has been saved in clipboard
risks  .  Press CTRL+SHIFT+C to share the clipboard with another qube.
risks  .  Local clipboard will be erased is 45 seconds

As well, if no identity is active, you can query the passphrase like this:

user@vault $ risks gpgpass PrimeWizard

Identity backup

We now have an identity and some tombs to backup. We already formatted a backup device in the first section, so we now mount it with the following command. Note that there is no mapper like with the hush device, so we must specify a device file as argument.

user@vault [ PrimeWizard ] $ risks backup mount /dev/xvdj 
Enter passphrase for /dev/xvdj: 
risks  .  Backup unlocked and mounted on /tmp/pendrive

There are several subcommands available, to back up different things. The first one we use only backs the raw hush image:

user@vault [ PrimeWizard ] $ risks backup hush 
risks  .  Backing hush partition
risks  .  Hush device is unmounted and closed
1800404992 bytes (1.8 GB, 1.7 GiB) copied, 146 s, 12.4 MB/s
107+1 records in
107+1 records out
1800404992 bytes (1.8 GB, 1.7 GiB) copied, 145.796 s, 12.3 MB/s
risks  .  Done backing hush partition

Note that we don't have to close the active identity, nor that we will have to mount the hush device again before closing it, since in order to close, we don't need access to private keys.

We can also back up the currently active identity. A few things to note:

  • As you can see, it also backs the hush device raw image.
  • Since the identity has no backup directory set up yet, the command initializes the directory accordingly (with fscrypt).

When backing up the current identity, we get the following output:

user@vault [ PrimeWizard ] $ risks backup identity
risks  .  Setting graveyard backup for this identity
risks  .  Backing up current identity data and hush partition
risks  .  Backing hush partition
risks  .  Hush device is unmounted and closed
1800404992 bytes (1.8 GB, 1.7 GiB) copied, 144 s, 12.5 MB/s
107+1 records in
107+1 records out
1800404992 bytes (1.8 GB, 1.7 GiB) copied, 144.448 s, 12.5 MB/s
risks  .  Done backing hush partition
risks  .  Done backing current identity and hush device

Deleting tombs and identities

We can also delete the Data tomb we have created above, along with its backup equivalent.

Note that this command can take some time, as the wipe program has to make several passes over the tomb-file, potentially twice if the backup is deleted also. Just wait for it to finish. On a vault qube with 2 vCPUS at maximum 1.8Gz, the command above takes 4 min 27 sec.

user@vault [ PrimeWizard ] $ risks tomb delete Data --backup
risks  .  Deleting tomb Data
risks  .  Deleting tomb backup
risks  .  Deleted tomb Data

We can also delete the entire identity with the following command. This will consequently take a quite large amount of time, as there are many tomb-files to delete, and potentially their backup equivalents.

user@vault [ PrimeWizard ] $ risks identity delete PrimeWizard --backup

Using master keys

Sometimes one needs to have direct access to the master GPG key, for things like renewing key expiry dates, generating new subkeys (shown in the next section), etc. risks offers a few simple commands to easily import/remove the master GPG private key to/from the backup medium.

First, to import the key from the backup (requires access to backup pendrive):

user@vault [ PrimeWizard ] $ risks backup mount /dev/xvdj
user@vault [ PrimeWizard ] $ risks gpg import PrimeWizard
risks [W] /----------------------------------------/
risks  >  Warning! HUSH is writable              
risks  >  Do not unplug without umounting it !   
risks  >  /----------------------------------------/ 
risks  .  Importing GPG private key in keyring

Then, do whatever you have to do involving the private key (here you can go to the next section, and come back after it). Finally, once deeds are done, remove the master private key:

user@vault [ PrimeWizard ] $ risks gpg remove
risks [W] /----------------------------------------/
risks  >  Warning! HUSH is writable              
risks  >  Do not unplug without umounting it !   
risks  >  /----------------------------------------/ 
risks  .  Wiping private GPG key 2CFA2C17B7D5281E245EA0494AD3AA45EFDAEC40.key from keyring
risks  .  HUSH is now mounted read-only
risks  .  Removed private key from keyring

Generating new subkeys

The CLI also gives a command to add new GPG and/or SSH key/pairs. The set of allowed/completed key algorithms is relatively restrained, and other parameters will be left to gpg/ssh-keygen tools to set.

Currently, our GPG keyring looks like this:

sec   ed25519/0xA8B254FEC73366AE 2022-10-18 [SC]
      Key fingerprint = CB40 6A1D 1A3C CA60 9956  F2E3 A8B2 54FE C733 66AE
      Keygrip = 2CFA2C17B7D5281E245EA0494AD3AA45EFDAEC40
uid                   [ultimate] PrimeWizard <primewizard@proton.me>
ssb   cv25519/0x2B736FBBFF56392A 2022-10-18 [E] [expires: 2023-10-19]
      Key fingerprint = 0C01 6573 E7B7 AC47 7361  B70C 2B73 6FBB FF56 392A
      Keygrip = B0B9FAE3D2F34F9193286275E5C8F26C3BEF2476
ssb   ed25519/0x28B0BB56CC6F4B3D 2022-10-18 [S] [expires: 2023-10-19]
      Key fingerprint = A87E 732E E70A 2B71 8DFC  A9CE 28B0 BB56 CC6F 4B3D
      Keygrip = 0F7304E3323EBC6B8EB34F12E9367978DB8291BE
ssb   ed25519/0x1EF0D14329DF74D7 2022-10-18 [A] [expires: 2023-10-19]
      Key fingerprint = B943 B321 AE43 AB21 BFDD  6DCA 1EF0 D143 29DF 74D7
      Keygrip = E0D6C257D768B7DD08023A8EB0AC1121D8A1F71B

We first generate a new pair of GPG subkeys, one for signing and the other for encryption, specifying the algorithm to use (defaults to ed25519).

user@vault [ PrimeWizard ] $ risks gpg generate dsa --sign 
risks  .  Generating GPG subkey
risks  .  Type: dsa
risks  .  Signing: 1 | Encrypting: 
risks [W] /----------------------------------------/
risks  >  Warning! HUSH is writable              
risks  >  Do not unplug without umounting it !   
risks  >  /----------------------------------------/ 
risks  .  Fingerprint: CB406A1D1A3CCA609956F2E3A8B254FEC73366AE
risks  .  Generating signature subkey-pair
risks  .  HUSH is now mounted read-only
risks  .  Successfully generated GPG subkey(s)

user@vault [ PrimeWizard ] $ risks gpg generate --encrypt
... similar output ...

Two new subkeys have been added to the keyring:

... output above ...
ssb   dsa2048/0xBA4E20AB8382119C 2023-02-23 [S] [expires: 2023-02-23]
      Key fingerprint = FFB6 635B 72B7 3EF9 C635  5FBA BA4E 20AB 8382 119C
      Keygrip = E041FC88C308A785711B114EC1BB62BAF82DFB2B
ssb   cv25519/0x04FBF5191AB440F8 2023-02-23 [E]
      Key fingerprint = F11B DFE3 BDB1 FA95 7AD5  4340 04FB F519 1AB4 40F8
      Keygrip = 34B848F8057A8A6B0A86933E263C8FBC5760BAB1

(Here we only give gpg as positional argument, as the 2nd argument, the expiry, is optional: if not specified, the keys don't expire). We could also only specify --sign or --encr, in which case only one key is generated.

The equivalent command for generating a new SSH keypair.

user@vault [ PrimeWizard ] $ risks ssh generate rsa
risks  .  Generating SSH keypair
risks  .  Type: rsa
risks  .  Successfully generated new SSH keypair

user@vault [ PrimeWizard ] $ ssh-add -l
4096 SHA256:Gap7ZinEjb9RLZJuKMA6dz2IAITB4dkmujw8rJrvMhc primewizard@proton.me (RSA)
256 SHA256:pacso8CICfKPrfCQWrfLtHic7cSmZsshpBKrPPAJjRk primewizard@proton.me (ED25519)

user@vault [ PrimeWizard ] $ tree ~/.ssh
.ssh/
├── PrimeWizard-rsa-26900       # Our newly generated keys
├── PrimeWizard-rsa-26900.pub   # on those lines
├── id_ed25519
├── id_ed25519.pub
└── ssh-add                     # Multi-key loading script

As you see the name of the key files is half-randomly generated: however the SSH tomb includes the multi-key ssh-add script, which will automatically load this key in the keyring along with the others.