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}