Skip to main content

co_didcomm/messages/
jws.rs

1use crate::{
2    helpers::create_fallback_getter,
3    messages::helpers::{serialization_base64_buffer, serialization_base64_jwm_header},
4    Jwk,
5    JwmHeader,
6};
7
8/// Signature data for [JWS](https://datatracker.ietf.org/doc/html/rfc7515) envelopes.
9/// They can be used per recipient in [General JWS JSON](https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.1),
10/// triggered by using [`.as_jws`][crate::Message::as_jws()] or as a single signature for the entire JWS in
11/// [Flattened JWS JSON](https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.2), triggered by
12/// [`.as_flat_jws`][crate::Message::as_flat_jws()].
13#[derive(Serialize, Deserialize, Debug, Clone)]
14pub struct Signature {
15    /// integrity protected header elements
16    #[serde(default)]
17    #[serde(skip_serializing_if = "Option::is_none")]
18    #[serde(with = "serialization_base64_jwm_header")]
19    pub protected: Option<JwmHeader>,
20
21    /// header elements that are not integrity protected
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub header: Option<JwmHeader>,
24
25    /// signature computed over protected header elements
26    #[serde(default)]
27    #[serde(with = "serialization_base64_buffer")]
28    pub signature: Vec<u8>,
29}
30
31impl Signature {
32    /// Creates a new `Signature` that can be used in JWS `signatures` property or
33    /// as top-level (flattened) property in flattened JWS JSON serialization.
34    ///
35    /// # Arguments
36    ///
37    /// * `protected` - JWM header protected by signing
38    ///
39    /// * `header` - JWM header not protected by signing
40    ///
41    /// * `signature` - signature over JWS payload and protected header
42    pub fn new(
43        protected: Option<JwmHeader>,
44        header: Option<JwmHeader>,
45        signature: Vec<u8>,
46    ) -> Self {
47        Signature {
48            protected,
49            header,
50            signature,
51        }
52    }
53
54    create_fallback_getter!(header, protected, alg, String);
55
56    create_fallback_getter!(header, protected, cty, String);
57
58    create_fallback_getter!(header, protected, enc, String);
59
60    create_fallback_getter!(header, protected, epk, Jwk);
61
62    create_fallback_getter!(header, protected, jku, String);
63
64    create_fallback_getter!(header, protected, jwk, Jwk);
65
66    create_fallback_getter!(header, protected, kid, String);
67
68    create_fallback_getter!(header, protected, skid, String);
69}
70
71/// A struct to generate and serialize [JWS](https://datatracker.ietf.org/doc/html/rfc7515)
72/// envelopes for DIDComm messages.
73#[derive(Serialize, Deserialize, Debug)]
74pub struct Jws {
75    /// base64 encoded payload of the JWS
76    pub payload: String,
77
78    /// Top-level signature for flat JWS JSON messages.
79    /// Will be ignored if `signatures` is not `None`
80    #[serde(flatten)]
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub signature: Option<Signature>,
83
84    /// Pre-recipient signatures for flat JWS JSON messages.
85    /// If not `None`, will be preferred over `signature`.
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub signatures: Option<Vec<Signature>>,
88}
89
90impl Jws {
91    /// Creates a new [general JWS](https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.1)
92    /// object with signature values per recipient.
93    ///
94    /// # Arguments
95    ///
96    /// * `payload` - payload with encoded data
97    ///
98    /// * `signatures` - signature values per recipient
99    pub fn new(payload: String, signatures: Vec<Signature>) -> Self {
100        Jws {
101            payload,
102            signature: None,
103            signatures: Some(signatures),
104        }
105    }
106
107    /// Creates a new [flattened JWS](https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.2)
108    /// object with signature information on JWS' top level.
109    ///
110    /// # Arguments
111    ///
112    /// * `payload` - payload with encoded data
113    ///
114    /// * `signatures_value` - signature value that is used on JWS top-level
115    pub fn new_flat(payload: String, signature_value: Signature) -> Self {
116        Jws {
117            payload,
118            signature: Some(signature_value),
119            signatures: None,
120        }
121    }
122}