detached_jws/
lib.rs

1//! Encoding, decoding, signing and verification ([Detached JWS](https://medium.com/gin-and-tonic/implementing-detached-json-web-signature-9ca5665ddcfc))
2//!
3//! Signing and verifying is done through the [`Sign`] and [`Verify`] traits.
4//!
5//! # Example with writer:
6//! ```
7//! use openssl::pkey::PKey;
8//! use openssl::rsa::Rsa;
9//! use openssl::{hash::MessageDigest};
10//! use openssl::{
11//!     rsa::Padding,
12//!     sign::{Signer, Verifier},
13//! };
14//! use serde_json::{json, Map, Value};
15//! use std::io::{Write};
16//! use detached_jws::{SerializeJwsWriter, DeserializeJwsWriter};
17//!
18//! let keypair = PKey::from_rsa(Rsa::generate(2048).unwrap()).unwrap();
19//!
20//! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
21//! signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
22//!
23//! let mut header = Map::new();
24//! header.insert("custom".to_owned(), json!("custom_value"));
25//!
26//! let mut writer = SerializeJwsWriter::new(Vec::new(),
27//!        "PS256".to_owned(),
28//!        header,
29//!        signer).unwrap();
30//! writer.write_all(&[0, 1, 2, 3]);
31//! writer.write_all(&[4, 5, 6]);
32//!
33//! let jws = writer.finish().unwrap();
34//!
35//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap();
36//! verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
37//!
38//! let mut writer = DeserializeJwsWriter::new(&jws,
39//!     |h| Some(verifier)
40//! ).unwrap();
41//! writer.write_all(&[0, 1, 2, 3]);
42//! writer.write_all(&[4, 5, 6]);
43//!
44//! let verified_headers = writer.finish().unwrap();
45//!
46//! assert_eq!(
47//!     verified_headers.get("custom").unwrap().as_str().unwrap(),
48//!     "custom_value"
49//! );
50//! ```
51//!
52//! # Simple example:
53//! ```
54//! use openssl::pkey::PKey;
55//! use openssl::rsa::Rsa;
56//! use openssl::{hash::MessageDigest};
57//! use openssl::{
58//!     rsa::Padding,
59//!     sign::{Signer, Verifier},
60//! };
61//! use serde_json::{json, Map, Value};
62//!
63//! let keypair = PKey::from_rsa(Rsa::generate(2048).unwrap()).unwrap();
64//!
65//! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
66//! signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
67//!
68//! let mut header = Map::new();
69//! header.insert("custom".to_owned(), json!("custom_value"));
70//!
71//! let payload = vec![0, 1, 2, 3, 4, 5, 6];
72//!
73//! let jws = detached_jws::serialize(
74//!     "PS256".to_owned(),
75//!     header,
76//!     &mut payload.as_slice(),
77//!     signer,
78//! )
79//! .unwrap();
80//!
81//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap();
82//! verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
83//!
84//! let verified_headers =
85//!     detached_jws::deserialize(&jws, &mut payload.as_slice(), verifier).unwrap();
86//!
87//! assert_eq!(
88//!     verified_headers.get("custom").unwrap().as_str().unwrap(),
89//!     "custom_value"
90//! );
91//! ```
92pub mod decode;
93pub mod encode;
94
95pub mod openssl;
96
97use anyhow::Result;
98use serde_json::{value::Value, Map};
99use std::io::Read;
100use std::io::Write;
101
102pub use crate::decode::{deserialize, deserialize_selector, DeserializeJwsWriter};
103pub use crate::encode::{serialize, SerializeJwsWriter};
104
105pub type JwsHeader = Map<String, Value>;
106
107/// A signature signer
108pub trait Sign: Write {
109    fn get_sign(&self) -> Result<Vec<u8>>;
110
111    fn form_detached_jws(
112        self,
113        algorithm: String,
114        header: JwsHeader,
115        payload: &mut impl Read,
116    ) -> Result<Vec<u8>>
117    where
118        Self: Sized,
119    {
120        serialize(algorithm, header, payload, self)
121    }
122}
123
124/// A signature verifier
125pub trait Verify: Write {
126    fn verify(&self, signature: &[u8]) -> Result<bool>;
127
128    fn verify_jws_detached(
129        self,
130        jws: &impl AsRef<[u8]>,
131        payload: &mut impl Read,
132    ) -> Result<JwsHeader>
133    where
134        Self: Sized,
135    {
136        deserialize(jws, payload, self)
137    }
138}