1use askar_crypto::{
2    buffer::SecretBytes,
3    encrypt::{KeyAeadInPlace, KeyAeadMeta},
4    kdf::{FromKeyDerivation, KeyExchange},
5    random,
6    repr::{KeyGen, ToSecretBytes},
7};
8use std::borrow::Cow;
9
10use sha2::{Digest, Sha256};
11
12use crate::{
13    error::{ErrorKind, Result, ResultExt},
14    jwe::envelope::{Algorithm, EncAlgorithm, PerRecipientHeader, ProtectedHeader, Recipient, JWE},
15    jwk::ToJwkValue,
16    utils::crypto::{JoseKDF, KeyWrap},
17};
18
19pub(crate) fn encrypt<CE, KDF, KE, KW>(
20    plaintext: &[u8],
21    alg: Algorithm,
22    enc: EncAlgorithm,
23    sender: Option<(&str, &KE)>, recipients: &[(&str, &KE)],  ) -> Result<String>
26where
27    CE: KeyAeadInPlace + KeyAeadMeta + KeyGen + ToSecretBytes,
28    KDF: JoseKDF<KE, KW>,
29    KE: KeyExchange + KeyGen + ToJwkValue,
30    KW: KeyWrap + FromKeyDerivation,
31{
32    let (skid, skey) = match sender {
33        Some((skid, skey)) => (Some(skid), Some(skey)),
34        None => (None, None),
35    };
36
37    let mut rng = random::default_rng();
38    let cek = CE::generate(&mut rng).kind(ErrorKind::InvalidState, "Unable generate cek")?;
39
40    let apv = {
41        let mut kids = recipients.iter().map(|r| r.0).collect::<Vec<_>>();
42        kids.sort();
43        Sha256::digest(kids.join(".").as_bytes())
44    };
45
46    let epk = KE::generate(&mut rng).kind(ErrorKind::InvalidState, "Unable generate epk")?;
47
48    let protected = {
49        let epk = epk.to_jwk_public_value()?;
50        let apu = skid.map(|skid| base64::encode_config(skid, base64::URL_SAFE_NO_PAD));
51        let apv = base64::encode_config(apv, base64::URL_SAFE_NO_PAD);
52
53        let p = ProtectedHeader {
54            typ: Some(Cow::Borrowed("application/didcomm-encrypted+json")),
55            alg: alg.clone(),
56            enc,
57            skid,
58            apu: apu.as_deref(),
59            apv: &apv,
60            epk,
61        };
62
63        let p = serde_json::to_string(&p)
64            .kind(ErrorKind::InvalidState, "Unable serialize protected header")?;
65
66        base64::encode_config(&p, base64::URL_SAFE_NO_PAD)
67    };
68
69    let mut buf = {
70        let mut buf = SecretBytes::with_capacity(plaintext.len() + cek.aead_params().tag_length);
71
72        buf.extend_from_slice(plaintext);
73        buf
74    };
75
76    let (ciphertext, tag, tag_raw, iv) = {
77        let iv = CE::random_nonce();
79
80        let ciphertext_len = cek
81            .encrypt_in_place(&mut buf, &iv[..], protected.as_bytes())
82            .kind(ErrorKind::InvalidState, "Unable encrypt content")?;
83
84        let ciphertext = &buf.as_ref()[0..ciphertext_len];
85        let tag_raw = &buf.as_ref()[ciphertext_len..];
86
87        let ciphertext = base64::encode_config(&ciphertext, base64::URL_SAFE_NO_PAD);
88        let tag = base64::encode_config(&tag_raw, base64::URL_SAFE_NO_PAD);
89        let iv = base64::encode_config(&iv, base64::URL_SAFE_NO_PAD);
90
91        (ciphertext, tag, tag_raw, iv)
92    };
93
94    let encrypted_keys = {
95        let mut encrypted_keys: Vec<(&str, String)> = Vec::with_capacity(recipients.len());
96
97        for (kid, key) in recipients {
98            let kw = KDF::derive_key(
99                &epk,
100                skey,
101                &key,
102                alg.as_str().as_bytes(),
103                skid.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]),
104                apv.as_slice(),
105                &tag_raw,
106                false,
107            )
108            .kind(ErrorKind::InvalidState, "Unable derive kw")?; let encrypted_key = kw
111                .wrap_key(&cek)
112                .kind(ErrorKind::InvalidState, "Unable wrap key")?;
113
114            let encrypted_key = base64::encode_config(&encrypted_key, base64::URL_SAFE_NO_PAD);
115            encrypted_keys.push((kid.clone(), encrypted_key));
116        }
117
118        encrypted_keys
119    };
120
121    let recipients: Vec<_> = encrypted_keys
122        .iter()
123        .map(|(kid, encrypted_key)| Recipient {
124            header: PerRecipientHeader { kid },
125            encrypted_key: &encrypted_key,
126        })
127        .collect();
128
129    let jwe = JWE {
130        protected: &protected,
131        recipients,
132        iv: &iv,
133        ciphertext: &ciphertext,
134        tag: &tag,
135    };
136
137    let jwe = serde_json::to_string(&jwe).kind(ErrorKind::InvalidState, "Unable serialize jwe")?;
138
139    Ok(jwe)
140}
141
142#[cfg(test)]
143mod tests {
144    use askar_crypto::{
145        alg::{
146            aes::{A256CbcHs512, A256Gcm, A256Kw, AesKey},
147            chacha20::{Chacha20Key, XC20P},
148            p256::P256KeyPair,
149            x25519::X25519KeyPair,
150        },
151        encrypt::{KeyAeadInPlace, KeyAeadMeta},
152        jwk::FromJwk,
153        kdf::{ecdh_1pu::Ecdh1PU, ecdh_es::EcdhEs, FromKeyDerivation, KeyExchange},
154        repr::{KeyGen, KeyPublicBytes, KeySecretBytes, ToPublicBytes, ToSecretBytes},
155    };
156
157    use crate::{
158        error::ErrorKind,
159        jwe::{
160            self,
161            envelope::{Algorithm, EncAlgorithm},
162            test_support::*,
163        },
164        jwk::{FromJwkValue, ToJwkValue},
165        utils::crypto::{JoseKDF, KeyWrap},
166    };
167
168    #[test]
169    fn encrypt_works() {
170        _encrypt_works::<
171            AesKey<A256CbcHs512>,
172            Ecdh1PU<'_, X25519KeyPair>,
173            X25519KeyPair,
174            AesKey<A256Kw>,
175        >(
176            Some((ALICE_KID_X25519_1, ALICE_KEY_X25519_1, ALICE_PKEY_X25519_1)),
177            &[(BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1)],
178            Algorithm::Ecdh1puA256kw,
179            EncAlgorithm::A256cbcHs512,
180        );
181
182        _encrypt_works::<
183            AesKey<A256CbcHs512>,
184            Ecdh1PU<'_, X25519KeyPair>,
185            X25519KeyPair,
186            AesKey<A256Kw>,
187        >(
188            Some((ALICE_KID_X25519_1, ALICE_KEY_X25519_1, ALICE_PKEY_X25519_1)),
189            &[
190                (BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1),
191                (BOB_KID_X25519_2, BOB_KEY_X25519_2, BOB_PKEY_X25519_2),
192                (BOB_KID_X25519_3, BOB_KEY_X25519_3, BOB_PKEY_X25519_3),
193            ],
194            Algorithm::Ecdh1puA256kw,
195            EncAlgorithm::A256cbcHs512,
196        );
197
198        _encrypt_works::<AesKey<A256CbcHs512>, Ecdh1PU<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
199            Some((ALICE_KID_P256_1, ALICE_KEY_P256_1, ALICE_PKEY_P256_1)),
200            &[(BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1)],
201            Algorithm::Ecdh1puA256kw,
202            EncAlgorithm::A256cbcHs512,
203        );
204
205        _encrypt_works::<AesKey<A256CbcHs512>, Ecdh1PU<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
206            Some((ALICE_KID_P256_1, ALICE_KEY_P256_1, ALICE_PKEY_P256_1)),
207            &[
208                (BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1),
209                (BOB_KID_P256_2, BOB_KEY_P256_2, BOB_PKEY_P256_2),
210            ],
211            Algorithm::Ecdh1puA256kw,
212            EncAlgorithm::A256cbcHs512,
213        );
214
215        _encrypt_works::<
216            AesKey<A256CbcHs512>,
217            EcdhEs<'_, X25519KeyPair>,
218            X25519KeyPair,
219            AesKey<A256Kw>,
220        >(
221            None,
222            &[(BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1)],
223            Algorithm::EcdhEsA256kw,
224            EncAlgorithm::A256cbcHs512,
225        );
226
227        _encrypt_works::<
228            AesKey<A256CbcHs512>,
229            EcdhEs<'_, X25519KeyPair>,
230            X25519KeyPair,
231            AesKey<A256Kw>,
232        >(
233            None,
234            &[
235                (BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1),
236                (BOB_KID_X25519_2, BOB_KEY_X25519_2, BOB_PKEY_X25519_2),
237                (BOB_KID_X25519_3, BOB_KEY_X25519_3, BOB_PKEY_X25519_3),
238            ],
239            Algorithm::EcdhEsA256kw,
240            EncAlgorithm::A256cbcHs512,
241        );
242
243        _encrypt_works::<AesKey<A256CbcHs512>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
244            None,
245            &[(BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1)],
246            Algorithm::EcdhEsA256kw,
247            EncAlgorithm::A256cbcHs512,
248        );
249
250        _encrypt_works::<AesKey<A256CbcHs512>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
251            None,
252            &[
253                (BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1),
254                (BOB_KID_P256_2, BOB_KEY_P256_2, BOB_PKEY_P256_2),
255            ],
256            Algorithm::EcdhEsA256kw,
257            EncAlgorithm::A256cbcHs512,
258        );
259
260        _encrypt_works::<AesKey<A256Gcm>, EcdhEs<'_, X25519KeyPair>, X25519KeyPair, AesKey<A256Kw>>(
261            None,
262            &[(BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1)],
263            Algorithm::EcdhEsA256kw,
264            EncAlgorithm::A256Gcm,
265        );
266
267        _encrypt_works::<AesKey<A256Gcm>, EcdhEs<'_, X25519KeyPair>, X25519KeyPair, AesKey<A256Kw>>(
268            None,
269            &[
270                (BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1),
271                (BOB_KID_X25519_2, BOB_KEY_X25519_2, BOB_PKEY_X25519_2),
272                (BOB_KID_X25519_3, BOB_KEY_X25519_3, BOB_PKEY_X25519_3),
273            ],
274            Algorithm::EcdhEsA256kw,
275            EncAlgorithm::A256Gcm,
276        );
277
278        _encrypt_works::<AesKey<A256Gcm>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
279            None,
280            &[(BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1)],
281            Algorithm::EcdhEsA256kw,
282            EncAlgorithm::A256Gcm,
283        );
284
285        _encrypt_works::<AesKey<A256Gcm>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
286            None,
287            &[
288                (BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1),
289                (BOB_KID_P256_2, BOB_KEY_P256_2, BOB_PKEY_P256_2),
290            ],
291            Algorithm::EcdhEsA256kw,
292            EncAlgorithm::A256Gcm,
293        );
294
295        _encrypt_works::<
296            Chacha20Key<XC20P>,
297            EcdhEs<'_, X25519KeyPair>,
298            X25519KeyPair,
299            AesKey<A256Kw>,
300        >(
301            None,
302            &[(BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1)],
303            Algorithm::EcdhEsA256kw,
304            EncAlgorithm::Xc20P,
305        );
306
307        _encrypt_works::<
308            Chacha20Key<XC20P>,
309            EcdhEs<'_, X25519KeyPair>,
310            X25519KeyPair,
311            AesKey<A256Kw>,
312        >(
313            None,
314            &[
315                (BOB_KID_X25519_1, BOB_KEY_X25519_1, BOB_PKEY_X25519_1),
316                (BOB_KID_X25519_2, BOB_KEY_X25519_2, BOB_PKEY_X25519_2),
317                (BOB_KID_X25519_3, BOB_KEY_X25519_3, BOB_PKEY_X25519_3),
318            ],
319            Algorithm::EcdhEsA256kw,
320            EncAlgorithm::Xc20P,
321        );
322
323        _encrypt_works::<Chacha20Key<XC20P>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
324            None,
325            &[(BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1)],
326            Algorithm::EcdhEsA256kw,
327            EncAlgorithm::Xc20P,
328        );
329
330        _encrypt_works::<Chacha20Key<XC20P>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
331            None,
332            &[
333                (BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1),
334                (BOB_KID_P256_2, BOB_KEY_P256_2, BOB_PKEY_P256_2),
335            ],
336            Algorithm::EcdhEsA256kw,
337            EncAlgorithm::Xc20P,
338        );
339
340        _encrypt_works::<AesKey<A256Gcm>, EcdhEs<'_, P256KeyPair>, P256KeyPair, AesKey<A256Kw>>(
341            None,
342            &[
343                (BOB_KID_P256_1, BOB_KEY_P256_1, BOB_PKEY_P256_1),
344                (BOB_KID_P256_2, BOB_KEY_P256_2, BOB_PKEY_P256_2),
345            ],
346            Algorithm::Other("otherAlg".to_owned()),
347            EncAlgorithm::A256Gcm,
348        );
349        fn _encrypt_works<CE, KDF, KE, KW>(
352            alice: Option<(&str, &str, &str)>,
353            bob: &[(&str, &str, &str)],
354            alg: Algorithm,
355            enc_alg: EncAlgorithm,
356        ) where
357            CE: KeyAeadInPlace + KeyAeadMeta + KeyGen + ToSecretBytes + KeySecretBytes,
358            KDF: JoseKDF<KE, KW>,
359            KE: KeyExchange + KeyGen + ToJwkValue + FromJwkValue + ToPublicBytes + KeyPublicBytes,
360            KW: KeyWrap + FromKeyDerivation,
361        {
362            let alice = alice.map(|a| {
363                (
364                    a.0,
365                    KE::from_jwk(a.1).expect("Unable from_jwk"),
366                    KE::from_jwk(a.2).expect("Unable from_jwk"),
367                )
368            });
369
370            let alice_kid = alice.as_ref().map(|a| a.0);
371            let alice_priv = alice.as_ref().map(|a| (a.0, &a.1));
372            let alice_pub = alice.as_ref().map(|a| (a.0, &a.2));
373
374            let bob = bob
375                .iter()
376                .map(|b| {
377                    (
378                        b.0,
379                        KE::from_jwk(b.1).expect("Unable from_jwk"),
380                        KE::from_jwk(b.2).expect("Unable from_jwk"),
381                    )
382                })
383                .collect::<Vec<_>>();
384
385            let bob_priv: Vec<_> = bob.iter().map(|b| (b.0, &b.1)).collect();
386            let bob_pub: Vec<_> = bob.iter().map(|b| (b.0, &b.2)).collect();
387
388            let plaintext = "Some plaintext.";
389
390            let msg = jwe::encrypt::<CE, KDF, KE, KW>(
391                plaintext.as_bytes(),
392                alg.clone(),
393                enc_alg.clone(),
394                alice_priv,
395                &bob_pub,
396            )
397            .expect("Unable encrypt");
398
399            let mut buf = vec![];
400            let msg = jwe::parse(&msg, &mut buf).expect("Unable parse");
401
402            assert_eq!(msg.protected.alg, alg);
403            assert_eq!(msg.protected.enc, enc_alg);
404            assert_eq!(msg.jwe.recipients.len(), bob.len());
405
406            assert_eq!(msg.apu.as_deref(), alice_kid.map(str::as_bytes));
407
408            for recipient in &msg.jwe.recipients {
409                let bob_edge_priv = bob_priv
410                    .iter()
411                    .find(|b| recipient.header.kid == b.0)
412                    .expect("recipient not found.");
413
414                let plaintext_ = msg
415                    .decrypt::<CE, KDF, KE, KW>(alice_pub, *bob_edge_priv)
416                    .expect("unable decrypt.");
417
418                assert_eq!(plaintext_, plaintext.as_bytes());
419            }
420        }
421    }
422
423    #[test]
424    fn encrypt_works_no_sender() {
425        let bob_kid = BOB_KID_X25519_1;
426        let bob_pkey = X25519KeyPair::from_jwk(BOB_PKEY_X25519_1).expect("unable from_jwk");
427        let plaintext = "Some plaintext.";
428
429        let res = jwe::encrypt::<
430            AesKey<A256CbcHs512>,
431            Ecdh1PU<'_, X25519KeyPair>,
432            X25519KeyPair,
433            AesKey<A256Kw>,
434        >(
435            plaintext.as_bytes(),
436            Algorithm::Ecdh1puA256kw,
437            EncAlgorithm::A256cbcHs512,
438            None,
439            &[(bob_kid, &bob_pkey)],
440        );
441
442        let err = res.expect_err("res is ok");
443        assert_eq!(err.kind(), ErrorKind::InvalidState);
444        assert_eq!(format!("{}", err), "Invalid state: Unable derive kw: Invalid state: No sender key for ecdh-1pu: No sender key for ecdh-1pu");
445    }
446}