voa-openpgp

Crates.iovoa-openpgp
lib.rsvoa-openpgp
version0.6.2
created_at2025-09-10 18:29:00.992361+00
updated_at2026-01-09 12:59:58.604656+00
descriptionA library for using OpenPGP verifiers in VOA
homepagehttps://voa.archlinux.page
repositoryhttps://gitlab.archlinux.org/archlinux/alpm/voa
max_upload_size
id1832852
size248,253
Arne Christian Beer (Nukesor)

documentation

README

VOA-OpenPGP

A library for using OpenPGP verifiers in VOA.

See https://uapi-group.org/specifications/specs/file_hierarchy_for_the_verification_of_os_artifacts/#openpgp

Documentation

Examples

Import

OpenPGP certificates can be written to their dedicated directory structures in a VOA hierarchy.

It is supported to import single binary or ASCII-armored files, as well as directory structures that contain a number of OpenPGP packet files which comprise an OpenPGP certificate when concatenated (this structured form is in use by the archlinux-keyring project).

use voa_core::VerifierWriter;
use voa_openpgp::OpenPgpImport;
# use pgp::{
#     composed::{KeyType, SecretKeyParamsBuilder, SignedPublicKey, SubkeyParamsBuilder},
#     ser::Serialize,
#     types::Password,
# };
# use rand::thread_rng;
use tempfile::{NamedTempFile, tempdir};
#
# fn openpgp_cert() -> testresult::TestResult<SignedPublicKey> {
#     let mut signkey = SubkeyParamsBuilder::default();
#     signkey
#         .key_type(KeyType::Ed25519Legacy)
#         .can_sign(true)
#         .can_encrypt(false)
#         .can_authenticate(false);
#     let mut key_params = SecretKeyParamsBuilder::default();
#     key_params
#         .key_type(KeyType::Ed25519Legacy)
#         .can_certify(true)
#         .can_sign(false)
#         .can_encrypt(false)
#         .primary_user_id("John Doe <jdoe@example.org>".to_string())
#         .subkeys(vec![signkey.build()?]);
#
#     let secret_key_params = key_params.build()?;
#     let secret_key = secret_key_params.generate(thread_rng())?;
#
#     // Produce binding self-signatures that link all the components together
#     let signed = secret_key.sign(&mut thread_rng(), &Password::from(""))?;
#
#     let pubkey = SignedPublicKey::from(signed);
#     Ok(pubkey)
# }
# fn main() -> testresult::TestResult {

// Write a generic OpenPGP certificate to a temporary file.
let mut temp_file = NamedTempFile::new()?;
openpgp_cert()?.to_writer(&mut temp_file)?;
let input_path = temp_file.path();

// Import the OpenPGP certificate.
let import = OpenPgpImport::from_file(input_path)?;

// Prepare a temporary output directory.
let temp_dir = tempdir()?;
let output_dir = temp_dir.path();

// Write the OpenPGP verifier to a VOA hierarchy in the temporary output directory.
//
// There, the verifier is written to the configured directory, e.g.
// `os/purpose/context/openpgp/f1d2d2f924e986ac86fdf7b36c94bcdf32beec15.openpgp`
import.write_to_hierarchy(
    output_dir,
    "os".parse()?,
    "purpose".parse()?,
    Some("context".parse()?),
)?;

assert!(
    output_dir
        .join("os")
        .join("purpose")
        .join("context")
        .join("openpgp")
        .join(import.file_name())
        .exists()
);
# Ok(())
# }

Verification

Simple verification of artifacts using one or more OpenPGP signatures and verifiers from VOA is straight forward:

use std::{num::NonZero, path::PathBuf};
use voa_config::openpgp::{NumDataSignatures, OpenpgpSettings, PlainMode, VerificationMethod};
use voa_openpgp::{ModelBasedVerifier, OpenpgpCert, OpenpgpSignature, VoaOpenpgp};

# fn main() -> testresult::TestResult {
let voa = VoaOpenpgp::new();
let certs = voa.lookup("os".parse()?, "purpose".parse()?, "context".parse()?);

let config = OpenpgpSettings::new(
    NumDataSignatures::new(NonZero::new(1).expect("1")),
    VerificationMethod::Plain(PlainMode::default())).expect("OpenpgpSettings::new");
let model = ModelBasedVerifier::new(&config, &certs, &[]);

let file = PathBuf::from("/path/to/a/file.tar.zst");
let sigs = &[OpenpgpSignature::from_file(&PathBuf::from("/path/to/a/file.tar.zst.sig"))?];
let result = model.verify_file_with_signatures(&file, &sigs[..])?;

# Ok(())
# }

Contributing

Please refer to the contribution guidelines to learn how to contribute to this project.

License

This project can be used under the terms of the Apache-2.0 or MIT. Contributions to this project, unless noted otherwise, are automatically licensed under the terms of both of those licenses.

Commit count: 0

cargo fmt