From cb041ff45d1594c57597c862456dff4dfd4b8898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hlusi=C4=8Dka?= Date: Mon, 15 Jul 2024 01:36:16 +0200 Subject: [PATCH] Replace Argon2's pepper with a random root predecessor nonce --- Cargo.lock | 1 + Cargo.toml | 1 + README.md | 1 - benches/benches.rs | 19 +++-- cddl/registry.cddl | 3 +- src/cmd/mod.rs | 6 +- src/crypto/password_hash/argon2.rs | 51 +++++++------ src/crypto/password_hash/mod.rs | 2 - src/error.rs | 62 +++++++++++++++ src/record/key.rs | 17 +++-- src/record/mod.rs | 11 ++- src/record/path.rs | 6 +- src/registry.rs | 118 +++++++++++++++++++++++++---- tests/cddl.proptest-regressions | 1 + tests/cddl.rs | 2 +- tests/test.rs | 6 +- 16 files changed, 234 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0794241..febfb7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2052,6 +2052,7 @@ dependencies = [ "proptest", "proptest-arbitrary-interop", "proptest-derive", + "rand", "serde", "serde_with", "sha2", diff --git a/Cargo.toml b/Cargo.toml index c6e0b33..6b273af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ itertools = "0.13.0" proptest = "1.5.0" proptest-arbitrary-interop = "0.1.0" proptest-derive = "0.5.0" +rand = "0.8.5" serde = { version = "1.0.203", features = ["derive"] } serde_with = "3.8.1" sha2 = "0.10.8" diff --git a/README.md b/README.md index 8927d0e..0694b1a 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ Launch it by running the following: ``` ## TODO -* [ ] Replace Argon2's pepper with configured initial succession nonce, do not use pepper by default. * [ ] Splitting records into multiple files. * [x] Basic library implementation * [ ] Pad contents to a registry-wide constant length. diff --git a/benches/benches.rs b/benches/benches.rs index 18f6b79..cd91705 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -24,21 +24,20 @@ fn with_samples(samples: usize) -> Criterion { #[criterion(with_samples(10))] fn bench_hash_params(c: &mut Criterion) { let hash = RegistryConfigHash { - algorithm: PasswordHashAlgorithm::Argon2( - Argon2Params::default_with_random_pepper_of_recommended_length(OsRng), - ), + algorithm: PasswordHashAlgorithm::Argon2(Argon2Params::default()), output_length_in_bytes: ConfigParam::try_from(32).unwrap(), }; - let kdf = RegistryConfigKdf { - algorithm: KdfAlgorithm::Hkdf(HkdfParams { + let kdf = RegistryConfigKdf::builder() + .with_algorithm(KdfAlgorithm::Hkdf(HkdfParams { prf: HkdfPrf::Sha256, - }), - succession_nonce_length_in_bytes: ConfigParam::try_from(32).unwrap(), - file_name_length_in_bytes: ConfigParam::try_from(8).unwrap(), - }; + })) + .with_file_name_length_in_bytes(8) + .with_succession_nonce_length_in_bytes(32) + .build_with_random_root_predecessor_nonce(OsRng) + .unwrap(); let key = RecordKey { record_name: RecordName::from(b"hello".to_vec()), - predecessor_nonce: kdf.get_root_record_predecessor_nonce(), + predecessor_nonce: kdf.get_root_record_predecessor_nonce().clone(), }; c.bench_function("hash_params", |b| { diff --git a/cddl/registry.cddl b/cddl/registry.cddl index 1e98d08..8ecf42d 100644 --- a/cddl/registry.cddl +++ b/cddl/registry.cddl @@ -11,8 +11,9 @@ RRR_Registry = { }, kdf: { algorithm: RRR_KdfAlgorithm, - succession_nonce_length_in_bytes: uint .ge 16, file_name_length_in_bytes: uint .ge 1, + succession_nonce_length_in_bytes: uint .ge 16, + root_predecessor_nonce: bstr, ; .size (16..1000), ; The upper bound is arbitrary TODO: not supported by cddl-rs }, ? verifying_keys: [ * RRR_VerifyingKey ], } diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 5961751..ad670eb 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -147,7 +147,11 @@ async fn resolve_path( .next() .expect("record path should never be empty") .clone(), - predecessor_nonce: registry.config.kdf.get_root_record_predecessor_nonce(), + predecessor_nonce: registry + .config + .kdf + .get_root_record_predecessor_nonce() + .clone(), } .hash(®istry.config.hash) .await?; diff --git a/src/crypto/password_hash/argon2.rs b/src/crypto/password_hash/argon2.rs index 2ba4f42..bc61d3c 100644 --- a/src/crypto/password_hash/argon2.rs +++ b/src/crypto/password_hash/argon2.rs @@ -8,7 +8,6 @@ use proptest_derive::Arbitrary; use std::fmt::Debug; use crate::error::Result; -use aes_gcm::aead::rand_core::{CryptoRng, RngCore}; use argon2::Argon2; use serde::{Deserialize, Serialize}; use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -40,31 +39,19 @@ pub struct Argon2Params { /// Degree of parallelism. Between 1 and (2^24)-1. #[zeroize(skip)] pub p_cost: u32, - pub pepper: Secret>>, + pub pepper: Option>>>, } -impl Argon2Params { - pub fn default_with_pepper(pepper: impl Into>) -> Self { +impl Default for Argon2Params { + fn default() -> Self { Self { variant: Variant::Argon2id, m_cost: 1 << 10, // 1 MiB t_cost: 1 << 10, p_cost: 1, - pepper: Secret(BytesOrHexString(pepper.into())), + pepper: None, } } - - pub fn default_with_random_pepper( - mut rng: impl CryptoRng + RngCore, - ) -> Self { - let mut pepper = vec![0; PEPPER_BYTES]; - rng.fill_bytes(&mut pepper); - Self::default_with_pepper(pepper) - } - - pub fn default_with_random_pepper_of_recommended_length(rng: impl CryptoRng + RngCore) -> Self { - Self::default_with_random_pepper::<{ super::BYTES_HASH_PEPPER_RECOMMENDED }>(rng) - } } impl PasswordHash for Argon2Params { @@ -74,12 +61,20 @@ impl PasswordHash for Argon2Params { Variant::Argon2i => argon2::Algorithm::Argon2i, Variant::Argon2id => argon2::Algorithm::Argon2id, }; - let argon2 = Argon2::new_with_secret( - &self.pepper, - variant, - argon2::Version::V0x13, - argon2::Params::new(self.m_cost, self.t_cost, self.p_cost, Some(output.len()))?, - )?; + let argon2 = if let Some(pepper) = self.pepper.as_ref() { + Argon2::new_with_secret( + pepper, + variant, + argon2::Version::V0x13, + argon2::Params::new(self.m_cost, self.t_cost, self.p_cost, Some(output.len()))?, + )? + } else { + Argon2::new( + variant, + argon2::Version::V0x13, + argon2::Params::new(self.m_cost, self.t_cost, self.p_cost, Some(output.len()))?, + ) + }; argon2.hash_password_into(password, salt, output)?; Ok(()) @@ -95,9 +90,15 @@ prop_compose! { m_cost in (8 * p_cost)..(std::cmp::max(8 * p_cost + 1, 1 << log_max_cost)), t_cost in Just(t_cost), p_cost in Just(p_cost), - pepper in proptest::collection::vec(any::(), 0..(1 << 10)), + pepper in proptest::option::of(proptest::collection::vec(any::(), 0..(1 << 10))), ) -> Argon2Params { - Argon2Params { variant, m_cost, t_cost, p_cost, pepper: Secret(BytesOrHexString(pepper)) } + Argon2Params { + variant, + m_cost, + t_cost, + p_cost, + pepper: pepper.map(|pepper| Secret(BytesOrHexString(pepper))), + } } } diff --git a/src/crypto/password_hash/mod.rs b/src/crypto/password_hash/mod.rs index c505fa6..4cc7931 100644 --- a/src/crypto/password_hash/mod.rs +++ b/src/crypto/password_hash/mod.rs @@ -11,8 +11,6 @@ use crate::error::Result; pub mod argon2; -pub const BYTES_HASH_PEPPER_RECOMMENDED: usize = 32; - pub trait PasswordHash { fn hash_password(&self, password: &[u8], salt: &[u8], output: &mut [u8]) -> Result<()>; } diff --git a/src/error.rs b/src/error.rs index a1b76e0..235d936 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,8 +2,11 @@ use std::borrow::Cow; use async_fd_lock::LockError; use coset::RegisteredLabel; +use derive_more::From; use thiserror::Error; +use crate::registry::{ConfigParamTooLowError, ConfigParamTrait}; + pub type Result = std::result::Result; #[derive(Error, Debug)] @@ -44,6 +47,8 @@ pub enum Error { UnrecognizedEncryptionAlgorithm { alg: Option }, #[error("Failed to resolve collisions")] CollisionResolutionFailed, + #[error(transparent)] + InvalidParameter(#[from] InvalidParameterError), } impl From> for Error { @@ -53,3 +58,60 @@ impl From> for Error { } pub struct SignatureMismatch; + +#[derive(Error, Debug)] +#[error("Invalid parameter `{label}`: {source}")] +pub struct InvalidParameterError { + pub label: &'static str, + #[source] + pub source: Box, +} + +impl

From> for InvalidParameterError +where + P: ConfigParamTrait + 'static, +{ + fn from(value: ConfigParamTooLowError

) -> Self { + InvalidParameterError { + label: P::LABEL, + source: Box::new(value), + } + } +} + +#[derive(Error, Debug, From)] +#[error("{0}")] +pub struct GenericError(pub Cow<'static, str>); + +impl From<&'static str> for GenericError { + fn from(value: &'static str) -> Self { + Self(Cow::Borrowed(value)) + } +} + +impl From for GenericError { + fn from(value: String) -> Self { + Self(Cow::Owned(value)) + } +} + +pub trait OptionExt { + fn unwrap_builder_parameter( + &self, + label: &'static str, + ) -> std::result::Result; +} + +impl OptionExt for Option { + fn unwrap_builder_parameter( + &self, + label: &'static str, + ) -> std::result::Result { + self.as_ref().cloned().ok_or_else(|| InvalidParameterError { + label, + source: Box::new(GenericError::from( + "value is required but was not specified", + )), + }) + } +} diff --git a/src/record/key.rs b/src/record/key.rs index 2057ef6..a7fc9b0 100644 --- a/src/record/key.rs +++ b/src/record/key.rs @@ -3,14 +3,14 @@ use crate::crypto::kdf::KdfExt; use crate::crypto::password_hash::PasswordHash; use crate::error::Result; use crate::record::segment::{ - FragmentEncryptionKeyBytes, FragmentFileNameBytes, KdfUsage, - KdfUsageFragmentParameters, KdfUsageFragmentUsage, + FragmentEncryptionKeyBytes, FragmentFileNameBytes, KdfUsage, KdfUsageFragmentParameters, + KdfUsageFragmentUsage, }; use crate::registry::{Registry, RegistryConfigHash, RegistryConfigKdf}; use crate::utils::serde::{BytesOrHexString, Secret}; use async_trait::async_trait; -use std::ops::{Deref, DerefMut}; use std::fmt::Debug; +use std::ops::{Deref, DerefMut}; use zeroize::{Zeroize, ZeroizeOnDrop}; use super::{RecordName, SuccessionNonce}; @@ -70,7 +70,7 @@ impl HashedRecordKey { okm: &mut [u8], ) -> Result<()> { kdf_params - .algorithm + .get_algorithm() .derive_key_from_canonicalized_cbor(self, usage, okm)?; Ok(()) } @@ -101,13 +101,13 @@ impl HashedRecordKey { &self, kdf_params: &RegistryConfigKdf, ) -> Result { - let mut okm = - vec![0_u8; *kdf_params.succession_nonce_length_in_bytes as usize].into_boxed_slice(); + let mut okm = vec![0_u8; kdf_params.get_succession_nonce_length_in_bytes() as usize] + .into_boxed_slice(); self.derive_key(&KdfUsage::SuccessionNonce {}, kdf_params, &mut okm) .await?; - Ok(SuccessionNonce(Secret(okm))) + Ok(SuccessionNonce(Secret(BytesOrHexString(okm)))) } pub async fn derive_fragment_file_name( @@ -115,7 +115,8 @@ impl HashedRecordKey { kdf_params: &RegistryConfigKdf, fragment_parameters: &KdfUsageFragmentParameters, ) -> Result { - let mut okm = vec![0_u8; *kdf_params.file_name_length_in_bytes as usize].into_boxed_slice(); + let mut okm = + vec![0_u8; kdf_params.get_file_name_length_in_bytes() as usize].into_boxed_slice(); let usage = KdfUsage::Fragment { usage: KdfUsageFragmentUsage::FileName, parameters: fragment_parameters.clone(), diff --git a/src/record/mod.rs b/src/record/mod.rs index 892584c..74f4273 100644 --- a/src/record/mod.rs +++ b/src/record/mod.rs @@ -3,7 +3,7 @@ use crate::crypto::encryption::EncryptionAlgorithm; use crate::crypto::signature::SigningKey; use crate::error::{Error, Result}; use crate::registry::{Registry, WriteLock}; -use crate::utils::serde::{BytesOrAscii, Secret}; +use crate::utils::serde::{BytesOrAscii, BytesOrHexString, Secret}; use async_fd_lock::{LockRead, LockWrite}; use chrono::{DateTime, FixedOffset, TimeZone}; use coset::cbor::tag; @@ -15,9 +15,8 @@ use proptest::strategy::{BoxedStrategy, Strategy}; use proptest_arbitrary_interop::arb; use proptest_derive::Arbitrary; use segment::{ - FragmentFileNameBytes, FragmentKey, FragmentReadSuccess, - KdfUsageFragmentParameters, RecordNonce, RecordParameters, - RecordVersion, Segment, SegmentMetadata, + FragmentFileNameBytes, FragmentKey, FragmentReadSuccess, KdfUsageFragmentParameters, + RecordNonce, RecordParameters, RecordVersion, Segment, SegmentMetadata, }; use serde::{Deserialize, Serialize}; use std::ops::{Deref, DerefMut}; @@ -36,8 +35,8 @@ mod path; pub use key::*; pub use path::*; -#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)] -pub struct SuccessionNonce(pub(crate) Secret>); +#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] +pub struct SuccessionNonce(pub(crate) Secret>>); impl Deref for SuccessionNonce { type Target = [u8]; diff --git a/src/record/path.rs b/src/record/path.rs index 7280e35..9446978 100644 --- a/src/record/path.rs +++ b/src/record/path.rs @@ -81,7 +81,11 @@ impl HashRecordPath for RecordPath { .next() .expect("record path should never be empty") .clone(), - predecessor_nonce: registry.config.kdf.get_root_record_predecessor_nonce(), + predecessor_nonce: registry + .config + .kdf + .get_root_record_predecessor_nonce() + .clone(), } .hash(®istry.config.hash) .await?; diff --git a/src/registry.rs b/src/registry.rs index 4ffecbb..066f3e0 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -3,21 +3,21 @@ use crate::crypto::encryption::EncryptionAlgorithm; use crate::crypto::kdf::KdfAlgorithm; use crate::crypto::password_hash::PasswordHashAlgorithm; use crate::crypto::signature::{SigningKey, VerifyingKey}; -use crate::error::{Error, Result}; +use crate::error::{Error, InvalidParameterError, OptionExt, Result}; use crate::record::segment::{FragmentFileNameBytes, RecordNonce, RecordVersion}; -use crate::record::{ - HashRecordPath, Record, RecordReadVersionSuccess, SuccessionNonce, -}; -use crate::utils::serde::Secret; +use crate::record::{HashRecordPath, Record, RecordReadVersionSuccess, SuccessionNonce}; +use crate::utils::serde::{BytesOrHexString, Secret}; use async_fd_lock::{LockRead, LockWrite}; use async_scoped::TokioScope; use casey::pascal; use coset::{cbor::tag, CoseKey}; use derive_more::{Deref, DerefMut}; use proptest::arbitrary::{any, Arbitrary}; +use proptest::collection::vec; use proptest::prop_compose; -use proptest::strategy::{BoxedStrategy, Strategy}; +use proptest::strategy::{BoxedStrategy, Just, Strategy}; use proptest_derive::Arbitrary; +use rand::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; use std::fmt::Display; @@ -37,7 +37,7 @@ use tracing::warn; pub const BYTES_HASH_PEPPER_RECOMMENDED: usize = 32; pub trait ConfigParamTrait { - type T: Ord + Debug; + type T: Ord + Debug + Send + Sync + 'static; const LABEL: &'static str; // Better readability than `std::any::type_name`, because it does not contain the full path to the type. const TYPE_NAME: &'static str; @@ -240,19 +240,95 @@ impl Arbitrary for RegistryConfigHash { } } +#[derive(Default, Clone, Debug)] +pub struct RegistryConfigKdfBuilder { + algorithm: Option, + file_name_length_in_bytes: Option<::T>, + succession_nonce_length_in_bytes: Option<::T>, +} + +impl RegistryConfigKdfBuilder { + pub fn with_algorithm(&mut self, algorithm: KdfAlgorithm) -> &mut Self { + self.algorithm = Some(algorithm); + self + } + + pub fn with_file_name_length_in_bytes( + &mut self, + file_name_length_in_bytes: ::T, + ) -> &mut Self { + self.file_name_length_in_bytes = Some(file_name_length_in_bytes); + self + } + + pub fn with_succession_nonce_length_in_bytes( + &mut self, + succession_nonce_length_in_bytes: ::T, + ) -> &mut Self { + self.succession_nonce_length_in_bytes = Some(succession_nonce_length_in_bytes); + self + } + + pub fn build_with_random_root_predecessor_nonce( + &self, + mut csprng: impl RngCore + CryptoRng, + ) -> Result { + let algorithm = self.algorithm.unwrap_builder_parameter("algorithm")?; + let file_name_length_in_bytes = ConfigParam::try_from( + self.file_name_length_in_bytes + .unwrap_builder_parameter("file_name_length_in_bytes")?, + ) + .map_err(InvalidParameterError::from)?; + let succession_nonce_length_in_bytes = ConfigParam::try_from( + self.succession_nonce_length_in_bytes + .unwrap_builder_parameter("succession_nonce_length_in_bytes")?, + ) + .map_err(InvalidParameterError::from)?; + Ok(RegistryConfigKdf { + root_predecessor_nonce: { + let mut bytes = + vec![0_u8; *succession_nonce_length_in_bytes as usize].into_boxed_slice(); + csprng.fill_bytes(&mut bytes); + SuccessionNonce(Secret(BytesOrHexString(bytes))) + }, + algorithm, + file_name_length_in_bytes, + succession_nonce_length_in_bytes, + }) + } +} + +impl RegistryConfigKdfBuilder {} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct RegistryConfigKdf { - pub algorithm: KdfAlgorithm, - pub succession_nonce_length_in_bytes: ConfigParam, - pub file_name_length_in_bytes: ConfigParam, + algorithm: KdfAlgorithm, + file_name_length_in_bytes: ConfigParam, + succession_nonce_length_in_bytes: ConfigParam, + root_predecessor_nonce: SuccessionNonce, } impl RegistryConfigKdf { - pub fn get_root_record_predecessor_nonce(&self) -> SuccessionNonce { - // TODO: Replace with a configurable field - SuccessionNonce(Secret( - vec![0_u8; *self.succession_nonce_length_in_bytes as usize].into(), - )) + pub fn builder() -> RegistryConfigKdfBuilder { + Default::default() + } + + pub fn get_algorithm(&self) -> &KdfAlgorithm { + &self.algorithm + } + + pub fn get_file_name_length_in_bytes(&self) -> ::T { + *self.file_name_length_in_bytes + } + + pub fn get_succession_nonce_length_in_bytes( + &self, + ) -> ::T { + *self.succession_nonce_length_in_bytes + } + + pub fn get_root_record_predecessor_nonce(&self) -> &SuccessionNonce { + &self.root_predecessor_nonce } } @@ -261,8 +337,18 @@ prop_compose! { algorithm in any::(), succession_nonce_length_in_bytes in arb_config_param(128), file_name_length_in_bytes in arb_config_param(64), + )( + root_predecessor_nonce in vec(any::(), (*succession_nonce_length_in_bytes as usize)..=128), + algorithm in Just(algorithm), + succession_nonce_length_in_bytes in Just(succession_nonce_length_in_bytes), + file_name_length_in_bytes in Just(file_name_length_in_bytes), ) -> RegistryConfigKdf { - RegistryConfigKdf { algorithm, succession_nonce_length_in_bytes, file_name_length_in_bytes } + RegistryConfigKdf { + algorithm, + file_name_length_in_bytes, + succession_nonce_length_in_bytes, + root_predecessor_nonce: SuccessionNonce(Secret(BytesOrHexString(root_predecessor_nonce.into()))), + } } } diff --git a/tests/cddl.proptest-regressions b/tests/cddl.proptest-regressions index 99d1b92..a32f624 100644 --- a/tests/cddl.proptest-regressions +++ b/tests/cddl.proptest-regressions @@ -8,3 +8,4 @@ cc 287d5f6872c85c1b91dc23caa30db05d7660d4dbaa533ab0b839f1ad6911f476 # shrinks to cc 53dba0a3be87a542e319b810a75838c1f7a6f25864297e19e9e7948f993a984c # shrinks to input = _VerifyCddlRegistryArgs { config_with_signing_keys: RegistryConfigWithSigningKeys { signing_keys: [], config: RegistryConfig { hash: RegistryConfigHash { algorithm: Argon2(Argon2Params { variant: Argon2d, m_cost: 288, t_cost: 8, p_cost: 36, pepper: Secret }), kdf_input_length_in_bytes: ConfigParam(25), successor_nonce_length_in_bytes: ConfigParam(17) }, kdf: RegistryConfigKdf { algorithm: Hkdf(HkdfParams { prf: Sha512 }), file_name_length_in_bytes: ConfigParam(21) }, verifying_keys: [] } } } cc 839af26b7476f2e2b13ff45663cd929bd3a8d2b30cb2459c93a263608525d15c # shrinks to input = _VerifyCddlRegistryArgs { config_with_signing_keys: RegistryConfigWithSigningKeys { signing_keys: [], config: RegistryConfig { hash: RegistryConfigHash { algorithm: Argon2(Argon2Params { variant: Argon2d, m_cost: 8, t_cost: 15, p_cost: 1, pepper: Secret }), kdf_input_length_in_bytes: ConfigParam(121), successor_nonce_length_in_bytes: ConfigParam(119) }, kdf: RegistryConfigKdf { algorithm: Hkdf(HkdfParams { prf: Sha512 }), file_name_length_in_bytes: ConfigParam(30) }, verifying_keys: [] } } } cc be44eefb8ba98ff0c66520db33a40b0ee6143bef1fabf640443b673523646ff6 # shrinks to input = _VerifyCddlRecordArgs { record: Record { metadata: RecordMetadata(Map({HashableCborValue(Integer(Integer(1))): Tag(0, Text("-262144-12-31T00:00:01-24:00"))})), data: b"" } } +cc 389b5f2d6f4f756558ada265984367ed9bfc0ead2d2faa13bb46087ea7694843 # shrinks to input = _VerifyCddlFragmentArgs { config_with_signing_keys: RegistryConfigWithSigningKeys { signing_keys: [], config: RegistryConfig { hash: RegistryConfigHash { algorithm: Argon2(Argon2Params { variant: Argon2d, m_cost: 288, t_cost: 3, p_cost: 36, pepper: Some(Secret) }), output_length_in_bytes: ConfigParam(110) }, kdf: RegistryConfigKdf { algorithm: Hkdf(HkdfParams { prf: Sha512 }), file_name_length_in_bytes: ConfigParam(2), succession_nonce_length_in_bytes: ConfigParam(113), root_predecessor_nonce: SuccessionNonce(Secret) }, verifying_keys: [] } }, segment: Segment { metadata: SegmentMetadata(Map({HashableCborValue(Integer(Integer(1))): Bool(true)})), data: b"0\x03\x96%C\x0e\xb7\xc5l\x93H\xbbM\xed\xec]\x1fnP\xa9|\x91\xc3\xee\xd8\xedO(\x86\xdb\x1f="… }, encryption_algorithm: None } diff --git a/tests/cddl.rs b/tests/cddl.rs index ed88d1c..8f71fe2 100644 --- a/tests/cddl.rs +++ b/tests/cddl.rs @@ -105,7 +105,7 @@ async fn verify_cddl_fragment( } = config_with_signing_keys; let record_key = RecordKey { record_name: Default::default(), - predecessor_nonce: config.kdf.get_root_record_predecessor_nonce(), // TODO + predecessor_nonce: config.kdf.get_root_record_predecessor_nonce().clone(), }; let hashed_record_key = record_key.hash(&config.hash).await.unwrap(); let fragment_key = FragmentKey { diff --git a/tests/test.rs b/tests/test.rs index 70eda90..e03a4fc 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -74,7 +74,11 @@ fn hash_registry_tree_recursive<'a, L: std::fmt::Debug + Sync + 'a>( predecessor_nonce: if let Some(predecessor_nonce) = predecessor_nonce { predecessor_nonce.clone() } else { - registry.config.kdf.get_root_record_predecessor_nonce() + registry + .config + .kdf + .get_root_record_predecessor_nonce() + .clone() }, }; let hashed_record_key = record_key.hash(®istry.config.hash).await.unwrap();