Documentation
// SPDX-FileCopyrightText: Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0

//! **A very small implementation of a modern subset of OpenPGP**
//!
//! [minipgp6](https://codeberg.org/minipgp6/) is a very lean OpenPGP software stack 🔐🤏.
//!
//! It implements a carefully delineated subset of
//! [RFC 9580 (OpenPGP)](https://www.rfc-editor.org/info/rfc9580/) and
//! [RFC 9980 (PQC in OpenPGP)](https://www.rfc-editor.org/info/rfc9980/).
//!
//! ### Project focus
//!
//! Extreme simplicity is a central goal of minipgp6.
//!
//! Therefore, minipgp6 does not implement backward compatibility with many of the currently common
//! OpenPGP formats.[^no-legacy]
//! Specifically, it does not handle "v4" (or older) key material or signatures.
//! It also does not support any pre-AEAD encryption formats.
//!
//! [^no-legacy]: As a consequence, minipgp6 contains *no code* that deals with legacy algorithms
//! (such as SHA1, RSA, DSA, ...).
//! In addition, the codebase can omit non-trivial amounts of assorted business logic that
//! support for the previous OpenPGP [RFC 4880](https://www.rfc-editor.org/info/rfc4880/) would
//! require.
//!
//! minipgp6 does not support all algorithms that RFC 9580 specifies and allows.
//! Instead, it focuses on the [subset of algorithms](https://codeberg.org/minipgp6/#algorithms)
//! that the RFC mandates, as a sound common denominator.
//!
//! ### Interoperability
//!
//! At the same time, minipgp6 also aims to be highly interoperable with the large and growing field
//! of modern OpenPGP implementations.
//!
//! Even though minipgp6 limits itself to modern OpenPGP formats, a [large set of
//! libraries](https://codeberg.org/minipgp6/#interop-with-other-openpgp-implementations)
//! interoperate seamlessly with the RFC 9580 formats that minipgp6 supports
//! (in particular: "v6" keys, signatures based on Ed25519, and encryption based on X25519 and
//! AEAD).
//!
//! The composite PQC formats that minipgp6 supports (ML-KEM-768+X25519 and ML-DSA-65+Ed25519)
//! will also be supported by all modern libraries. However, many OpenPGP libraries don't enable
//! PQC support by default yet (while they wait for final ratification of the RFC).
//!
//! # Core minipgp6 crates
//!
//! minipgp is highly modular. It consists of the following set of core crates:
//!
//! ## `minipgp6`
//!
//! This is the top-level entry point that is aimed at most users of minipgp.
//!
//! It offers convenient high level abstractions.
//!
//! *NOTE: This crate is still *very* incomplete.*
//!
//! ### `minipgp6_frame`
//!
//! This crate deals with the packet framing of the OpenPGP wire format, including reading sequences
//! of packets.
//!
//! ### [`minipgp6_packet`]
//!
//! This crate deals with the OpenPGP wire format: Parsing and serializing OpenPGP data.
//!
//! It contains no cryptographic functionality.
//!
//! ### [`minipgp6_sign`]
//!
//! This crate deals with digital signatures.
//!
//! It can produce and verify signatures, including in the context of inline-signed messages.
//!
//! Note that OpenPGP uses the same signature mechanism for two logically distinct purposes:
//!
//! - Signatures over data (either "detached" or as "inline-signed messages")
//! - Signatures that occur as parts of composite OpenPGP key objects (to link components together,
//!   for life-cycle operations, for third-party certifications, etc.)
//!
//! ### [`minipgp6_encrypt`]
//!
//! This crate deals with encryption and decryption of data.
//!
//! Encryption/decryption in OpenPGP is typically a hybrid operation with two steps:
//!
//! - Encrypting or decrypting a symmetric "session key" (usually using asymmetric key material)
//! - Symetrically encrypting or decrypting the actual (potentially large) message payload. minipgp6
//!   only supports the modern AEAD-based v2 SEIPD symmetric data packet encryption format.
//!
//! This crate deals with both of the above steps, and also offers an abstraction that combines
//! both operations to process encrypted messages.
//!
//! ### [`minipgp6_lock`]
//!
//! This crate deals with password-locking and -unlocking of secret key material.
//!
//! The private key material in OpenPGP "secret key packets" can optionally be protected with a
//! password.
//!
//! This crate provides functionality to password-lock secret key packets.
//! Conversely, in order to use a locked secret key packet for cryptographic operations,
//! private key material must be temporarily unlocked (i.e. decrypted).
//!
//! ### [`minipgp6_validity`]
//!
//! This crate implements OpenPGP "validity" semantics.
//!
//! Its purpose is to determine which components of a composite OpenPGP key can be used in a
//! specific context.
//!
//! Validity semantics encompasses the "expiration" and "revocation" mechanisms, as well as other
//! signals such as "Key Flags" (which keyholders use to signal the intended application of
//! component keys).
//!
//! ---
//!
//! # Additional minipgp6 crates
//!
//! ## `minipgp6_armor`
//!
//! The core minipgp6 crates consider binary encoded OpenPGP the default, and do not deal
//! with OpenPGP "ASCII armor".
//!
//! However, this separate crate offers functionality to produce and consume armored OpenPGP data.
//! It can be conveniently combined with the core minipgp libraries.
//!
//! ## `minipgp6_sop`
//!
//! A [Stateless OpenPGP (SOP)](https://dkg.gitlab.io/openpgp-stateless-cli/)
//! CLI tool based on minipgp6.

pub mod keygen;
pub mod lifecycle;
pub mod locking;

// FIXME: placeholder while the crate is not used yet
use minipgp6_validity as _;

/// minipgp6 version, via Cargo.toml
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Error type for minipgp6-composed
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum Error {
    /// Locked key packet in a place where unlocking is not supported
    #[error("Password-locked private key material is currently unsupported here")]
    LockingUnsupported,

    /// Can't unlock a secret key packet with the available passwords
    #[error("Can't unlock secret key packet")]
    CantUnlock,

    /// Error from minipgp6_packet
    #[error("Packet error: {0}")]
    Packet(#[from] minipgp6_packet::Error),

    /// Error from minipgp6_sign
    #[error("Signature error: {0}")]
    Signature(#[from] minipgp6_sign::Error),

    /// Error from minipgp6_encrypt
    #[error("Encryption error: {0}")]
    Encryption(#[from] minipgp6_encrypt::Error),

    /// General error that contains a message string
    #[error("Error: {0}")]
    Message(String),

    /// Io error
    #[error("Io error: {0}")]
    Io(#[from] std::io::Error),
}