Skip to content

Commit a0595e1

Browse files
committed
feat(data-packages): update implementation with in-place implementation to prevent allocating
1 parent ce07644 commit a0595e1

File tree

1 file changed

+54
-44
lines changed
  • rust-workspace/crates/ntc-data-packages/src/crypto

1 file changed

+54
-44
lines changed

rust-workspace/crates/ntc-data-packages/src/crypto/mod.rs

+54-44
Original file line numberDiff line numberDiff line change
@@ -3,89 +3,90 @@ use hpke::{
33
kdf::HkdfSha384,
44
kem::X25519HkdfSha256,
55
rand_core::{CryptoRng, RngCore},
6-
HpkeError, Kem, OpModeR, OpModeS,
6+
HpkeError, Kem as KemTrait, OpModeR, OpModeS,
77
};
8+
type Kem = X25519HkdfSha256;
9+
type Kdf = HkdfSha384;
10+
type Aead = ChaCha20Poly1305;
811

912
// TODO: Define info that can be sent alongside the message - application defined
1013
// like which sk to use etc.
1114
const INFO_STR: &[u8] = b"test";
1215

13-
pub struct SealedMessage {
14-
pub encapped_key: <X25519HkdfSha256 as Kem>::EncappedKey,
15-
pub ciphertext: Box<[u8]>,
16-
pub tag: AeadTag<ChaCha20Poly1305>,
16+
pub struct SealedMessage<'a> {
17+
pub encapped_key: <Kem as KemTrait>::EncappedKey,
18+
pub ciphertext: &'a [u8],
19+
pub tag: AeadTag<Aead>,
1720
}
1821

19-
pub fn seal_message<R: CryptoRng + RngCore>(
20-
msg: &[u8],
22+
pub fn seal_message_in_place<'a, R: CryptoRng + RngCore>(
23+
msg: &'a mut [u8],
2124
associated_data: &[u8],
22-
pk_recipient: <X25519HkdfSha256 as Kem>::PublicKey,
23-
pk_sender: <X25519HkdfSha256 as Kem>::PublicKey,
24-
sk_sender: <X25519HkdfSha256 as Kem>::PrivateKey,
25+
pk_recipient: <Kem as KemTrait>::PublicKey,
26+
pk_sender: <Kem as KemTrait>::PublicKey,
27+
sk_sender: <Kem as KemTrait>::PrivateKey,
2528
csprng: &mut R,
26-
) -> Result<SealedMessage, HpkeError> {
27-
let (encapsulated_key, mut encryption_context) =
28-
hpke::setup_sender::<ChaCha20Poly1305, HkdfSha384, X25519HkdfSha256, _>(
29-
&OpModeS::Auth((sk_sender, pk_sender)),
30-
&pk_recipient,
31-
INFO_STR,
32-
csprng,
33-
)?;
34-
let mut msg_copy = msg.to_vec();
35-
// TODO: add option for seal in place or use seal in place instead?
36-
let tag = encryption_context.seal_in_place_detached(&mut msg_copy, associated_data)?;
29+
) -> Result<SealedMessage<'a>, HpkeError> {
30+
let (encapsulated_key, mut encryption_context) = hpke::setup_sender::<Aead, Kdf, Kem, _>(
31+
&OpModeS::Auth((sk_sender, pk_sender)),
32+
&pk_recipient,
33+
INFO_STR,
34+
csprng,
35+
)?;
36+
37+
let tag = encryption_context.seal_in_place_detached(msg, associated_data)?;
3738

3839
Ok(SealedMessage {
3940
encapped_key: encapsulated_key,
40-
ciphertext: msg_copy.into_boxed_slice(),
41+
// TODO: don't copy
42+
ciphertext: msg,
4143
tag,
4244
})
4345
}
4446

45-
pub fn unseal_message(
46-
sealed_message: &SealedMessage,
47+
pub fn unseal_message_in_place<'a>(
48+
ciphertext: &'a mut [u8],
49+
encapped_key: <Kem as KemTrait>::EncappedKey,
50+
tag: AeadTag<Aead>,
4751
associated_data: &[u8],
48-
sk_recipient: <X25519HkdfSha256 as Kem>::PrivateKey,
49-
pk_sender: <X25519HkdfSha256 as Kem>::PublicKey,
50-
) -> Result<Box<[u8]>, HpkeError> {
51-
let mut receiver_ctx = hpke::setup_receiver::<ChaCha20Poly1305, HkdfSha384, X25519HkdfSha256>(
52+
sk_recipient: <Kem as KemTrait>::PrivateKey,
53+
pk_sender: <Kem as KemTrait>::PublicKey,
54+
) -> Result<&'a [u8], HpkeError> {
55+
let mut receiver_ctx = hpke::setup_receiver::<Aead, Kdf, Kem>(
5256
&OpModeR::Auth(pk_sender),
5357
&sk_recipient,
54-
&sealed_message.encapped_key,
58+
&encapped_key,
5559
INFO_STR,
5660
)?;
5761

58-
let mut cipherext_copy = sealed_message.ciphertext.to_vec();
59-
60-
receiver_ctx.open_in_place_detached(
61-
&mut cipherext_copy,
62-
associated_data,
63-
&sealed_message.tag,
64-
)?;
62+
receiver_ctx.open_in_place_detached(ciphertext, associated_data, &tag)?;
6563

6664
// Rename for clarity
67-
let plaintext = cipherext_copy;
65+
let plaintext = ciphertext;
6866

69-
Ok(plaintext.into_boxed_slice())
67+
Ok(plaintext)
7068
}
7169

7270
#[cfg(test)]
7371
mod test {
7472

73+
use std::vec;
74+
7575
use super::*;
7676
use rand::{self, SeedableRng};
7777

7878
#[test]
7979
fn seal_unseal_roundtrip_success() {
80-
let message = b"some string to send";
80+
let message = vec![1, 2, 3, 4];
81+
let mut message_copy = message.clone();
8182
let associated_data = b"some associated data to share";
8283
let (sk_sender, pk_sender) = X25519HkdfSha256::derive_keypair(b"some key material");
8384
let (sk_recipient, pk_recipient) =
8485
X25519HkdfSha256::derive_keypair(b"some different key material");
8586
let mut csprng = rand::rngs::StdRng::from_entropy();
8687

87-
let sealed_message = seal_message(
88-
message,
88+
let sealed_message = seal_message_in_place(
89+
&mut message_copy,
8990
associated_data,
9091
pk_recipient,
9192
pk_sender.clone(),
@@ -94,9 +95,18 @@ mod test {
9495
)
9596
.unwrap();
9697

97-
let unsealed_message =
98-
unseal_message(&sealed_message, associated_data, sk_recipient, pk_sender).unwrap();
98+
let mut ciphertext = sealed_message.ciphertext.to_vec();
99+
100+
let unsealed_message = unseal_message_in_place(
101+
&mut ciphertext,
102+
sealed_message.encapped_key,
103+
sealed_message.tag,
104+
associated_data,
105+
sk_recipient,
106+
pk_sender,
107+
)
108+
.unwrap();
99109

100-
assert_eq!(unsealed_message, message.to_vec().into_boxed_slice());
110+
assert_eq!(unsealed_message, message);
101111
}
102112
}

0 commit comments

Comments
 (0)