Skip to main content

co_didcomm/messages/headers/
jwm.rs

1#[cfg(feature = "raw-crypto")]
2use crate::crypto::{CryptoAlgorithm, SignatureAlgorithm};
3use crate::{Jwk, MessageType};
4
5/// JWM Header as specified in [RFC](https://tools.ietf.org/html/draft-looker-jwm-01#section-2.3)
6/// With single deviation - allows raw text JWM to support DIDComm spec
7///
8/// Designed to work for both [JWE](https://tools.ietf.org/html/rfc7516) and [JWS](https://tools.ietf.org/html/rfc7515) message types.
9///
10/// `iv` property is not explicitly listed in the registered properties on the RFC but is present
11///     within example lists - used here as DIDComm crypto nonce sharing property.
12#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
13pub struct JwmHeader {
14    pub typ: MessageType,
15
16    // Some(String) if JWM is JWE encrypted.
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub enc: Option<String>,
19
20    // None if raw text message, Some(key ID) otherwise.
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub kid: Option<String>,
23
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub skid: Option<String>,
26
27    // None if raw text message, Some(String) for
28    //  both JWE and/or JWS.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub alg: Option<String>,
31
32    // Refers to a resource for a set of JSON-encoded public keys, one of
33    // which corresponds to the key used to digitally sign the JWS.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub jku: Option<String>,
36
37    // public key that corresponds to the key used to digitally sign the JWS.
38    // TODO: implement proper struct for it:
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub jwk: Option<Jwk>,
41
42    // Some(String) - serialized ephemeral public key.
43    // TODO: implement proper struct for it:
44    // https://tools.ietf.org/html/draft-looker-jwm-01#section-2.3
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub epk: Option<Jwk>,
47
48    // Some("JWM") should be used if nested JWS inside JWE.
49    // None otherwise is *STRONGLY RECOMMENDED* by RFC.
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub cty: Option<String>,
52}
53
54impl JwmHeader {
55    /// Setter of JOSE header properties to identify which signature alg used.
56    /// Modifies `typ` and `alg` headers.
57    #[cfg(feature = "raw-crypto")]
58    pub fn as_signed(&mut self, alg: &SignatureAlgorithm) {
59        self.typ = MessageType::DidCommJws;
60        match alg {
61            SignatureAlgorithm::EdDsa => {
62                self.alg = Some(String::from("EdDSA"));
63            }
64            SignatureAlgorithm::Es256 => {
65                self.alg = Some(String::from("ES256"));
66            }
67            SignatureAlgorithm::Es256k => {
68                self.alg = Some(String::from("ES256K"));
69            }
70        }
71    }
72
73    /// Setter of JOSE header properties to identify which crypto alg and key type used.
74    /// Modifies `enc`, `typ` and `alg` headers.
75    #[cfg(feature = "raw-crypto")]
76    pub fn as_encrypted(&mut self, alg: &CryptoAlgorithm) {
77        self.typ = MessageType::DidCommJwe;
78        match alg {
79            CryptoAlgorithm::A256GCM => {
80                self.enc = Some("A256GCM".into());
81                self.alg = Some("ECDH-1PU+A256KW".into());
82            }
83            CryptoAlgorithm::XC20P => {
84                self.enc = Some("XC20P".into());
85                self.alg = Some("ECDH-1PU+XC20PKW".into());
86            }
87            CryptoAlgorithm::A256CBC => {
88                self.alg = Some("A256CBC".into());
89                self.enc = Some("ECDH-1PU+A256KW".into())
90            }
91        }
92    }
93
94    pub fn kid(&mut self, kid: Option<String>) {
95        self.kid = kid;
96    }
97}
98
99impl Default for JwmHeader {
100    // Need to make sure nonce is 192 bit long unique for each message.
101    fn default() -> Self {
102        JwmHeader {
103            typ: MessageType::DidCommRaw,
104            enc: None,
105            kid: None,
106            skid: None,
107            epk: None,
108            alg: None,
109            cty: None,
110            jku: None,
111            jwk: None,
112        }
113    }
114}