pyrus_crypto/
lib.rs

1//! # Pyrus Crypto
2//!
3//! This crate provides an OpenPGP inspired crypto system. It is 
4//! based on generating certificates and using them to sign, encrypt 
5//! and decrypt messages. Because it is designed for use in a larger 
6//! application, this crate has some shortcomings. Mainly: symmetric 
7//! encryption requires supplying a sender's certificate.
8//!
9//! # Warning!
10//!
11//! This is not a serious crypto crate. It has no tests and is not reviewed 
12//! by third parties. It's security goes as far as the author's will 
13//! to make his school project seem secure.
14//!
15//! # Examples
16//!
17//! ## Generate and serialize a certificate keeping its secret parts:
18//! ```rust
19//! # use std::error::Error;
20//! use pyrus_crypto::prelude::*;
21//!
22//! # fn main() -> Result<(), Box<dyn Error>> {
23//! let larry = Cert::new("Larry <larry@gentoo.org>");
24//! let cert_bytes = postcard::to_stdvec(&larry)?;
25//!
26//! //.. save the certificate
27//! // use the certificate here
28//! # Ok(())
29//! # }
30//! ```
31//!
32//! ## Encrypt a message symmetrically using a passphrase:
33//! ```rust
34//! # use std::error::Error;
35//! use pyrus_crypto::prelude::*;
36//!
37//! # fn main() -> Result<(), Box<dyn Error>> {
38//! let larry: Cert = //..
39//! # Cert::new("Larry <larry@gentoo.org>");
40//! 
41//! let secret_text = b"This is a very secret message";
42//! let message = Message::new(&larry)?
43//!     .write(&secret_text[..])?
44//!     .encrypt_with(b"alcmdzmafia")? // don't use such passwords
45//!     .finalize()?;
46//! # Ok(())
47//! # }
48//! ```
49//!
50//! ## Sign and encrypt a message asymmetrically:
51//!
52//! Note that the certificates are behind an [`std::sync::Arc`]. 
53//! This is how they will usually appear in the wild.
54//! ```rust
55//! # use std::error::Error;
56//! use pyrus_crypto::prelude::*;
57//! # use std::sync::Arc;
58//!
59//! # fn main() -> Result<(), Box<dyn Error>> {
60//! let larry: Arc<Cert> = //..
61//! # Arc::new(Cert::new("Larry <larry@gentoo.org>"));
62//! let agentcow: Arc<Cert> = //..
63//! # Arc::new(Cert::new("agentcow"));
64//! let agenthorse: Arc<Cert> = //..
65//! # Arc::new(Cert::new("agenthorse"));
66//! let agentfox: Arc<Cert> = //..
67//! # Arc::new(Cert::new("agentfox"));
68//! let friends = vec![agentcow.clone(), agenthorse.clone()];
69//!
70//! let secret_text = b"Let's meet up in the evening";
71//! let msg = Message::new(&larry)?
72//!     .write(&secret_text[..])?
73//!     .sign()
74//!     .encrypt_for(&friends)?
75//!     .finalize()?;
76//! # Ok(())
77//! # }
78//! ```
79//!
80//! ## Decrypt a symmetrically encrypted message
81//! ```rust
82//! # use std::error::Error;
83//! use pyrus_crypto::prelude::*;
84//!
85//! # fn main() -> Result<(), Box<dyn Error>> {
86//! # let larry: Cert = Cert::new("Larry <larry@gentoo.org>");
87//! # let secret_text = b"This is a very secret message";
88//! # let message = Message::new(&larry)?
89//! #     .write(&secret_text[..])?
90//! #     .encrypt_with(b"alcmdzmafia")? // don't use such passwords
91//! #     .finalize()?;
92//! // another of the aforementioned shortcomings
93//! let dummy = Cert::new("dummy cert");
94//! // assume we already have a message
95//! let (_, content, sig) = message
96//!     .parse(&dummy)?
97//!     .decrypt_with(&b"alcmdzmafia"[..])?
98//!     .finalize();
99//!
100//! assert_eq!(&secret_text[..], &content[..]);
101//! assert!(sig.is_none()); // the message is not signed
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! ## Decrypt and verify a signed message
107//! ```rust
108//! # use std::error::Error;
109//! use pyrus_crypto::prelude::*;
110//! # use std::sync::Arc;
111//!
112//! # fn main() -> Result<(), Box<dyn Error>> {
113//! let larry: Arc<Cert> = //..
114//! # Arc::new(Cert::new("Larry <larry@gentoo.org>"));
115//! let agentcow: Arc<Cert> = //..
116//! # Arc::new(Cert::new("agentcow"));
117//! let agenthorse: Arc<Cert> = //..
118//! # Arc::new(Cert::new("agenthorse"));
119//! let agentfox: Arc<Cert> = //..
120//! # Arc::new(Cert::new("agentfox"));
121//! # let friends = vec![agentcow.clone(), agenthorse.clone()];
122//!
123//! let secret_text = b"Let's meet up in the evening";
124//! # let message = Message::new(&larry)?
125//! #     .write(&secret_text[..])?
126//! #     .sign()
127//! #     .encrypt_for(&friends)?
128//! #     .finalize()?;
129//! let (message, content, signature) = message
130//!     .parse(&agentcow)? // decrypt using agentcow's certificate
131//!     .decrypt(larry.clone())?
132//!     .verify_signature(larry.clone())?
133//!     .finalize();
134//!
135//! assert_eq!(&secret_text[..], &content[..]);
136//! assert!(signature.unwrap()); // signature is Some and is good
137//!
138//! let fail = message
139//!     .parse(&agentfox)?
140//!     .decrypt(larry.clone());
141//! assert!(fail.is_err()); // cannot decrypt, not a recipient
142//! # Ok(())
143//! # }
144//! ```
145
146/// Certificate generation and serialization.
147pub mod cert;
148/// Message creation and parsing.
149pub mod message;
150/// Cryptographic primitives, the foundation of this crate.
151pub mod crypto;
152/// [`CryptoError`](crate::error::CryptoError) type and 
153/// [`Result<T>`](crate::error::Result) type specialization.
154pub mod error;
155/// Re-exports commonly used types
156pub mod prelude;
157
158/// Alias for the certificate's fingerprint type.
159///
160/// The hash type is [`blake3::Hash`].
161///
162/// # A note on equality
163/// To ensure constant time equality checking it is recommended to keep 
164/// the type as is. Check the [`blake3`] crate documentation for more 
165/// information.
166pub type Fingerprint = blake3::Hash;
167
168fn timestamp_bytes() -> [u8; 8] {
169    use std::time::{SystemTime, UNIX_EPOCH};
170    use rand_core::{OsRng, RngCore};
171    if let Ok(t) = SystemTime::now().duration_since(UNIX_EPOCH) {
172        let t = t.as_secs();
173        t.to_le_bytes()
174    } else {
175        let mut t = [0; 8];
176        OsRng.fill_bytes(&mut t);
177        t
178    }
179}