Skip to main content

pg_core/client/
mod.rs

1//! PostGuard client API.
2//!
3//! Used for:
4//! - Encrypting, signing, packing metadata (*sealing*),
5//! - Decrypting, verifying, unpacking metadata (*unsealing*).
6
7mod header;
8
9pub use header::{Algorithm, Header, Mode, RecipientHeader};
10
11#[cfg(feature = "rust")]
12pub mod rust;
13
14#[cfg(feature = "web")]
15pub mod web;
16
17use crate::artifacts::VerifyingKey;
18use crate::identity::Policy;
19use crate::util::*;
20use crate::{artifacts::SigningKeyExt, consts::*};
21use header::SignatureExt;
22use ibs::gg::Verifier;
23use serde::{Deserialize, Serialize};
24
25/// Returns a copy of a signing key whose policy is canonicalized.
26///
27/// The policy travels into the container, where a verifier derives the signer's
28/// identity from it. Canonicalizing it here means that identity matches the one
29/// the PKG derived when it issued this key — including for a verifier that
30/// predates the rule and derives the header bytes as they stand.
31pub(crate) fn canonical_signing_key(key: &SigningKeyExt) -> SigningKeyExt {
32    let mut key = key.clone();
33    key.policy.canonicalize();
34
35    key
36}
37
38/// A Sealer is used to encrypt and sign data using PostGuard.
39#[derive(Debug)]
40pub struct Sealer<'r, R, C> {
41    // The prebuilt header.
42    header: Header,
43
44    // An exclusive reference to a random number generator.
45    rng: &'r mut R,
46
47    // The flavor-specific configuration.
48    config: C,
49
50    // The public signing key. Used to sign public data, such as the header.
51    // The signature and claims are visible to outsiders.
52    pub_sign_key: SigningKeyExt,
53
54    // An optional private signing key.
55    // The signature and claims are encrypted and not visible to outsiders.
56    priv_sign_key: Option<SigningKeyExt>,
57}
58
59impl<'r, R, C> Sealer<'r, R, C> {
60    /// Add a private signing key and policy.
61    ///
62    /// This policy is safe to include private data as it is encrypted after signing.
63    pub fn with_priv_signing_key(mut self, mut priv_sign_key: SigningKeyExt) -> Self {
64        // See `canonical_signing_key`; this policy reaches the wire too.
65        priv_sign_key.policy.canonicalize();
66
67        self.priv_sign_key = Some(priv_sign_key);
68        self
69    }
70}
71
72/// An Unsealer is used to decrypt and verify data using PostGuard.
73///
74/// Unsealing is a two-step process:
75///
76/// 1. First the header is read. This yields information for whom the message is encrypted. Using
77///    this information the user can retrieve a user secret key.
78///
79/// 2. Then, the user has input the user secret key and the recipient for which decryption should
80///    take place.
81#[derive(Debug)]
82pub struct Unsealer<R, C: UnsealerConfig> {
83    /// The version found before the raw header.
84    pub version: u16,
85
86    /// The parsed header.
87    pub header: Header,
88
89    /// The verified public identity which was used to sign the header.
90    pub pub_id: Policy,
91
92    // The input.
93    r: R,
94
95    // The implementation-specific configuration.
96    config: C,
97
98    // The message verifier.
99    verifier: Verifier,
100
101    // The message verifier key.
102    vk: VerifyingKey,
103}
104
105/// Sender verification result.
106#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
107pub struct VerificationResult {
108    /// The public signing verified claims.
109    pub public: Policy,
110
111    /// The private signing verified claims.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub private: Option<Policy>,
114}
115
116/// Sealer configuration.
117///
118/// This trait is sealed, you cannot implement it yourself.
119#[doc(hidden)]
120pub trait SealerConfig: sealed::SealerConfig {}
121
122/// Unsealer configuration.
123///
124/// This trait is sealed, you cannot implement it yourself.
125#[doc(hidden)]
126pub trait UnsealerConfig: sealed::UnsealerConfig {}
127
128pub(crate) mod sealed {
129    pub trait UnsealerConfig {}
130    pub trait SealerConfig {}
131}
132
133#[cfg(any(feature = "stream", target_arch = "wasm32"))]
134impl From<futures::io::Error> for crate::error::Error {
135    fn from(e: futures::io::Error) -> Self {
136        Self::FuturesIO(e)
137    }
138}
139
140#[cfg(feature = "stream")]
141fn stream_mode_checked(h: &Header) -> Result<(u32, (u64, Option<u64>)), crate::error::Error> {
142    let (segment_size, size_hint) = match h {
143        Header {
144            mode:
145                Mode::Streaming {
146                    segment_size,
147                    size_hint,
148                },
149            ..
150        } => (segment_size, size_hint),
151        _ => return Err(crate::error::Error::ModeNotSupported(h.mode)),
152    };
153
154    if *segment_size > MAX_SYMMETRIC_CHUNK_SIZE {
155        return Err(crate::error::Error::ConstraintViolation);
156    }
157
158    Ok((*segment_size, *size_hint))
159}