Skip to content

Commit

Permalink
add test vector integration test, fix arg orders
Browse files Browse the repository at this point in the history
  • Loading branch information
jbr committed Apr 22, 2022
1 parent 1949a69 commit 550e995
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,7 @@ crate-type = ["cdylib", "rlib"]
lto = true

[dev-dependencies]
hex = { version = "0.4.3", features = ["serde"] }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
wasm-bindgen-test = "0.3.30"
6 changes: 3 additions & 3 deletions src/base_mode_open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ pub fn base_mode_open(
config: &Config,
private_key: &[u8],
encapped_key: &[u8],
ciphertext: &[u8],
info: &[u8],
ciphertext: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, HpkeError> {
let Config { aead, kdf, kem } = *config;
let open = match_algo!(aead, kdf, kem, open);
open(private_key, ciphertext, encapped_key, info, aad)
open(private_key, encapped_key, info, ciphertext, aad)
}

fn open<AeadT, KdfT, KemT>(
private_key: &[u8],
ciphertext: &[u8],
encapped_key: &[u8],
info: &[u8],
ciphertext: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, HpkeError>
where
Expand Down
8 changes: 4 additions & 4 deletions src/base_mode_seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ This will return an `Result::Err` variant if:
#[cfg(feature = "base-mode-seal")]
pub fn base_mode_seal(
config: &Config,
pk_recip: &[u8],
recipient_public_key: &[u8],
info: &[u8],
plaintext: &[u8],
aad: &[u8],
) -> Result<EncappedKeyAndCiphertext, HpkeError> {
let Config { aead, kdf, kem } = *config;
let seal = match_algo!(aead, kdf, kem, seal);
seal(pk_recip, info, plaintext, aad)
seal(recipient_public_key, info, plaintext, aad)
}

fn seal<AeadT, KdfT, KemT>(
pk_recip: &[u8],
recipient_public_key: &[u8],
info: &[u8],
plaintext: &[u8],
aad: &[u8],
Expand All @@ -49,7 +49,7 @@ where
{
let (encapped_key, ciphertext) = hpke::single_shot_seal::<AeadT, KdfT, KemT, _>(
&hpke::OpModeS::Base,
&from_bytes(pk_recip)?,
&from_bytes(recipient_public_key)?,
info,
plaintext,
aad,
Expand Down
8 changes: 4 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ impl Config {
#[cfg(feature = "base-mode-seal")]
pub fn base_mode_seal(
&self,
pk_recip: &[u8],
recipient_public_key: &[u8],
info: &[u8],
plaintext: &[u8],
aad: &[u8],
) -> Result<EncappedKeyAndCiphertext, HpkeError> {
base_mode_seal(self, pk_recip, info, plaintext, aad)
base_mode_seal(self, recipient_public_key, info, plaintext, aad)
}

/**
Expand All @@ -77,12 +77,12 @@ impl Config {
pub fn base_mode_open(
&self,
private_key: &[u8],
ciphertext: &[u8],
encapped_key: &[u8],
info: &[u8],
ciphertext: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, HpkeError> {
base_mode_open(self, private_key, ciphertext, encapped_key, info, aad)
base_mode_open(self, private_key, encapped_key, info, ciphertext, aad)
}

/// Attempt to convert three u16 ids into a valid config. The id mappings are defined in the draft.
Expand Down
2 changes: 1 addition & 1 deletion tests/round_trip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn test_round_trip(config: Config) {
.into_parts();

let plaintext = config
.base_mode_open(&private_key, &encapped_key, &ciphertext, APP_INFO, AAD)
.base_mode_open(&private_key, &encapped_key, APP_INFO, &ciphertext, AAD)
.unwrap_or_else(|e| panic!("problem with {config:?} base_mode_open ({e:?})"));

assert_eq!(
Expand Down
1 change: 1 addition & 0 deletions tests/test-vectors.json

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions tests/vectors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use hpke_dispatch::Config;
use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct EncryptionRecord {
#[serde(with = "hex")]
aad: Vec<u8>,
#[serde(with = "hex", rename = "ct")]
ciphertext: Vec<u8>,
#[serde(with = "hex")]
nonce: Vec<u8>,
#[serde(with = "hex", rename = "pt")]
plaintext: Vec<u8>,
}

/// This structure corresponds to the format of the JSON test vectors included with the HPKE
/// RFC. Only a subset of fields are used; all intermediate calculations are ignored.
#[derive(Deserialize, Debug)]
struct TestVector {
mode: u16,
kem_id: u16,
kdf_id: u16,
aead_id: u16,
#[serde(with = "hex")]
info: Vec<u8>,
#[serde(with = "hex", rename = "enc")]
encapped_key: Vec<u8>,
#[serde(with = "hex", rename = "skRm")]
serialized_private_key: Vec<u8>,
#[serde(with = "hex")]
base_nonce: Vec<u8>,
encryptions: Vec<EncryptionRecord>,
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn decrypt_test_vectors() {
let test_vectors: Vec<TestVector> =
serde_json::from_str(include_str!("./test-vectors.json")).unwrap(); // https://github.com/cfrg/draft-irtf-cfrg-hpke/raw/master/test-vectors.json

let test_vectors = test_vectors
.into_iter()
.filter(|v| v.mode == 0)
.filter_map(|test_vector| {
let config =
Config::try_from_ids(test_vector.aead_id, test_vector.kdf_id, test_vector.kem_id)
.ok()?;

Some((config, test_vector))
})
.collect::<Vec<_>>();

for (config, test_vector) in test_vectors {
for encryption in &test_vector.encryptions {
if encryption.nonce != test_vector.base_nonce {
continue;
}

let plaintext = config
.base_mode_open(
&test_vector.serialized_private_key,
&test_vector.encapped_key,
&test_vector.info,
&encryption.ciphertext,
&encryption.aad,
)
.unwrap_or_else(|e| {
panic!("{e:?}\n\n{config:?}\n\n{encryption:#?}\n\n{test_vector:#?}")
});

assert_eq!(plaintext, encryption.plaintext);
}
}
}

0 comments on commit 550e995

Please sign in to comment.