11 releases (6 breaking)

0.7.0 Aug 17, 2023
0.5.0 Apr 4, 2023
0.4.2 Jan 18, 2023
0.4.1 Dec 22, 2022
0.2.0 Jun 16, 2021

#908 in Cryptography

Download history 26/week @ 2024-02-19 45/week @ 2024-02-26 11/week @ 2024-03-04 14/week @ 2024-03-11 57/week @ 2024-03-18 31/week @ 2024-03-25

115 downloads per month
Used in 3 crates

MIT license

97KB
1.5K SLoC

Rust Interface for the Stateless OpenPGP Interface

A set of types and traits formalizing the Stateless OpenPGP Protocol. Currently, SOP is only defined as a command line interface, but we are working on a C Interface. This interface is the Rust equivalent of the yet to be defined C API.

To use this as a consumer, you will need a concrete implementation of the interface, such as sequoia-sop.

Example use

Given a reference to a [SOP] implementation, which is the main entry point for every SOP operation, generate keys, extract certs, sign, verify, encrypt, and decrypt:

let alice_sec = sop.generate_key()?
    .userid("Alice Lovelace <alice@openpgp.example>")
    .generate()?;
let alice_pgp = sop.extract_cert()?
    .keys(&alice_sec)?;

let bob_sec = sop.generate_key()?
    .userid("Bob Babbage <bob@openpgp.example>")
    .generate()?;
let bob_pgp = sop.extract_cert()?
    .keys(&bob_sec)?;

let statement = b"Hello World :)";
let mut data = Cursor::new(&statement);
let (_micalg, signature) = sop.sign()?
    .mode(ops::SignAs::Text)
    .keys(&alice_sec)?
    .data(&mut data)?;

let verifications = sop.verify()?
    .certs(&alice_pgp)?
    .signatures(&signature)?
    .data(&mut Cursor::new(&statement))?;
assert_eq!(verifications.len(), 1);

let mut statement_cur = Cursor::new(&statement);
let (_session_key, ciphertext) = sop.encrypt()?
    .sign_with_keys(&alice_sec)?
    .with_certs(&bob_pgp)?
    .plaintext(&mut statement_cur)?
    .to_vec()?;

let mut ciphertext_cur = Cursor::new(&ciphertext);
let (_, plaintext) = sop.decrypt()?
    .with_keys(&bob_sec)?
    .ciphertext(&mut ciphertext_cur)?
    .to_vec()?;
assert_eq!(&plaintext, statement);

The above snippet is the equivalent of the following SOP command line example from the SOP spec:

$ sop generate-key "Alice Lovelace <alice@openpgp.example>" > alice.sec
$ sop extract-cert < alice.sec > alice.pgp

$ sop sign --as=text alice.sec < statement.txt > statement.txt.asc
$ sop verify announcement.txt.asc alice.pgp < announcement.txt

$ sop encrypt --sign-with=alice.sec bob.pgp < msg.eml > encrypted.asc
$ sop decrypt alice.sec < ciphertext.asc > cleartext.out

Notes for SOP implementers

This section is for those who implement the interface using some OpenPGP implementation.

Command Line Interface

This crate contains an implementation of the Stateless OpenPGP Command Line Interface in terms of the Rust types and traits. Once you implemented the traits, you get the command line interface basically for free by adding this snippet to your Cargo.toml:

[[bin]]
path = "src/main.rs"
required-features = ["cli"]

[features]
cli = ["sop/cli"]

And creating src/main.rs along the lines of:

fn main() {
    sop::cli::main(&MySOPImplementation::default());
}

Dependencies

~0.3–11MB
~107K SLoC