The Keystore

The keystore, as the name implies, stores keys, or, to be precise, transferable public keys. It is part of the high-level interface, and hence we need to add sequoia to the [dependencies] section:

sequoia = { git = "https://gitlab.com/sequoia-pgp/sequoia.git" }

Now let’s see how we can use the store:

#[macro_use] // For armored!
extern crate openpgp;
extern crate sequoia;
use sequoia::{core, store};

fn main() {
    let mut reader = armored!(
        "-----BEGIN PGP PUBLIC KEY BLOCK-----

         mQENBFpxtsABCADZcBa1Q3ZLZnju18o0+t8LoQuIIeyeUQ0H45y6xUqyrD5HSkVM
         [...]
         -----END PGP PUBLIC KEY BLOCK-----"
    );

    // Provide some context.
    let ctx = core::Context::new("org.sequoia-pgp.guide").unwrap();

If you want to use the high-level interface, you need to create a Context. Sequoia tries to be useful for a wide range of applications with different requirements and thread models. Therefore, you need to give Sequoia a little bit of context so that we can accommodate your needs. Context::new(..) creates a context with reasonable defaults.

Furthermore, Sequoia provides every application with its own namespace, e.g. for the keystore. Therefore, you need to provide a reversed fully-qualified domain name that you control that identifies your application.

    // Parse TPK.
    let tpk = openpgp::TPK::from_reader(&mut reader).unwrap();

    // Open a store.
    let store = store::Store::open(&ctx, "default").unwrap();

    // Store the TPK.
    store.import("Ἀριστοτέλης", &tpk).unwrap();
}

All right, we stored a key. If you built the sq tool, we can use it to inspect the store:

$ sq --domain org.sequoia-pgp.guide store default list
+-------------+----------------------------------------------------+
| label       | fingerprint                                        |
+-------------+----------------------------------------------------+
| Ἀριστοτέλης | 7DCA 58B5 4EB1 4316 9DDE  E15F 247F 6DAB C849 14FE |
+-------------+----------------------------------------------------+

A keystore maps labels to TPKs. Here, default is the name of the store, Ἀριστοτέλης is the label, and it is mapped to the key we imported. We can ask for a log of changes related to that label and key:

$ sq --domain org.sequoia-pgp.guide store default log Ἀριστοτέλης
+------------------+------------------------------------------------+
| timestamp        | message                                        |
+------------------+------------------------------------------------+
| 2018-02-06 15:27 | Update successful                              |
| 2018-02-06 15:25 | New binding Ἀριστοτέλης -> 247F 6DAB C849 14FE |
+------------------+------------------------------------------------+

First of all, we see that we created a new binding in the store. Shortly after that, Sequoia successfully updated the key from the key servers. Sequoia updates keys stored in the keystore in accordance with your network policy. This makes sure that key updates and revocations are discovered in a timely manner.

Now let’s get the key back:

    let tpk_ = store.lookup("Ἀριστοτέλης").unwrap().tpk().unwrap();
    assert_eq!(tpk.fingerprint(), tpk_.fingerprint());