Skip to content

Commit 2381129

Browse files
authored
Adding key history validation checks (#417)
1 parent 86365d6 commit 2381129

File tree

2 files changed

+127
-5
lines changed

2 files changed

+127
-5
lines changed

akd/src/tests.rs

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ async fn test_publish_op_makes_no_get_requests<TC: Configuration>() -> Result<()
11251125
// ("hello10", "hello10")
11261126
// ("hello11", "hello11")
11271127
let mut updates = vec![];
1128-
for i in 0..1 {
1128+
for i in 0..2 {
11291129
updates.push((
11301130
AkdLabel(format!("hello1{i}").as_bytes().to_vec()),
11311131
AkdValue(format!("hello1{i}").as_bytes().to_vec()),
@@ -1153,7 +1153,7 @@ async fn test_publish_op_makes_no_get_requests<TC: Configuration>() -> Result<()
11531153

11541154
// create more updates
11551155
let mut updates = vec![];
1156-
for i in 0..1 {
1156+
for i in 0..2 {
11571157
updates.push((
11581158
AkdLabel(format!("hello1{i}").as_bytes().to_vec()),
11591159
AkdValue(format!("hello1{}", i + 1).as_bytes().to_vec()),
@@ -1188,7 +1188,7 @@ async fn test_simple_lookup_for_small_tree<TC: Configuration>() -> Result<(), Ak
11881188
// ("hello10", "hello10")
11891189
// ("hello11", "hello11")
11901190
let mut updates = vec![];
1191-
for i in 0..1 {
1191+
for i in 0..2 {
11921192
updates.push((
11931193
AkdLabel(format!("hello1{i}").as_bytes().to_vec()),
11941194
AkdValue(format!("hello1{i}").as_bytes().to_vec()),
@@ -1241,7 +1241,7 @@ async fn test_lookup_verify_invalid_version_number<TC: Configuration>() -> Resul
12411241
// ("hello10", "hello10")
12421242
// ("hello11", "hello11")
12431243
let mut updates = vec![];
1244-
for i in 0..1 {
1244+
for i in 0..2 {
12451245
updates.push((
12461246
AkdLabel(format!("hello1{i}").as_bytes().to_vec()),
12471247
AkdValue(format!("hello1{i}").as_bytes().to_vec()),
@@ -1306,6 +1306,95 @@ async fn test_publish_duplicate_entries<TC: Configuration>() -> Result<(), AkdEr
13061306
Ok(())
13071307
}
13081308

1309+
// Test key history verification for error handling of malformed key history proofs
1310+
test_config!(test_key_history_verify_malformed);
1311+
async fn test_key_history_verify_malformed<TC: Configuration>() -> Result<(), AkdError> {
1312+
let db = AsyncInMemoryDatabase::new();
1313+
let storage = StorageManager::new_no_cache(db);
1314+
let vrf = HardCodedAkdVRF {};
1315+
let akd = Directory::<TC, _, _>::new(storage, vrf.clone()).await?;
1316+
1317+
let mut rng = rand::rngs::OsRng;
1318+
for _ in 0..100 {
1319+
let mut updates = vec![];
1320+
updates.push((
1321+
AkdLabel(format!("label").as_bytes().to_vec()),
1322+
AkdValue::random(&mut rng),
1323+
));
1324+
akd.publish(updates.clone()).await?;
1325+
}
1326+
1327+
for _ in 0..100 {
1328+
let mut updates = vec![];
1329+
updates.push((
1330+
AkdLabel(format!("another label").as_bytes().to_vec()),
1331+
AkdValue::random(&mut rng),
1332+
));
1333+
akd.publish(updates.clone()).await?;
1334+
}
1335+
1336+
// Get the latest root hash
1337+
let EpochHash(current_epoch, root_hash) = akd.get_epoch_hash().await?;
1338+
// Get the VRF public key
1339+
let vrf_pk = akd.get_public_key().await?;
1340+
let target_label = AkdLabel(format!("label").as_bytes().to_vec());
1341+
1342+
let (key_history_proof, _) = akd
1343+
.key_history(&target_label, HistoryParams::default())
1344+
.await?;
1345+
1346+
// Normal verification should succeed
1347+
key_history_verify::<TC>(
1348+
vrf_pk.as_bytes(),
1349+
root_hash,
1350+
current_epoch,
1351+
target_label.clone(),
1352+
key_history_proof.clone(),
1353+
HistoryVerificationParams::default(),
1354+
)?;
1355+
1356+
let mut malformed_proof_1 = key_history_proof.clone();
1357+
malformed_proof_1.until_marker_vrf_proofs = key_history_proof.until_marker_vrf_proofs
1358+
[..key_history_proof.until_marker_vrf_proofs.len() - 1]
1359+
.to_vec();
1360+
let mut malformed_proof_2 = key_history_proof.clone();
1361+
malformed_proof_2.non_existence_until_marker_proofs = key_history_proof
1362+
.non_existence_until_marker_proofs
1363+
[..key_history_proof.non_existence_until_marker_proofs.len() - 1]
1364+
.to_vec();
1365+
let mut malformed_proof_3 = key_history_proof.clone();
1366+
malformed_proof_3.future_marker_vrf_proofs = key_history_proof.future_marker_vrf_proofs
1367+
[..key_history_proof.future_marker_vrf_proofs.len() - 1]
1368+
.to_vec();
1369+
let mut malformed_proof_4 = key_history_proof.clone();
1370+
malformed_proof_4.non_existence_of_future_marker_proofs = key_history_proof
1371+
.non_existence_of_future_marker_proofs[..key_history_proof
1372+
.non_existence_of_future_marker_proofs
1373+
.len()
1374+
- 1]
1375+
.to_vec();
1376+
1377+
// Malformed proof verification should fail
1378+
for malformed_proof in [
1379+
malformed_proof_1,
1380+
malformed_proof_2,
1381+
malformed_proof_3,
1382+
malformed_proof_4,
1383+
] {
1384+
assert!(key_history_verify::<TC>(
1385+
vrf_pk.as_bytes(),
1386+
root_hash,
1387+
current_epoch,
1388+
target_label.clone(),
1389+
malformed_proof,
1390+
HistoryVerificationParams::default(),
1391+
)
1392+
.is_err());
1393+
}
1394+
1395+
Ok(())
1396+
}
1397+
13091398
/*
13101399
=========== Test Helpers ===========
13111400
*/

akd_core/src/verify/history.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,23 @@ pub fn key_history_verify<TC: Configuration>(
116116
let next_marker = crate::utils::get_marker_version_log2(last_version) + 1;
117117
let final_marker = crate::utils::get_marker_version_log2(current_epoch);
118118

119-
// ***** Future checks below ***************************
119+
// Perform checks for expected number of until-marker proofs
120+
let expected_num_until_marker_proofs = (1 << next_marker) - last_version - 1;
121+
if expected_num_until_marker_proofs != proof.until_marker_vrf_proofs.len() as u64 {
122+
return Err(VerificationError::HistoryProof(format!(
123+
"Expected {} until-marker proofs, but got {}",
124+
expected_num_until_marker_proofs,
125+
proof.until_marker_vrf_proofs.len()
126+
)));
127+
}
128+
if proof.until_marker_vrf_proofs.len() != proof.non_existence_until_marker_proofs.len() {
129+
return Err(VerificationError::HistoryProof(format!(
130+
"Expected equal number of until-marker proofs, but got ({}, {})",
131+
proof.until_marker_vrf_proofs.len(),
132+
proof.non_existence_until_marker_proofs.len()
133+
)));
134+
}
135+
120136
// Verify the non-existence of future entries, up to the next marker
121137
for (i, version) in (last_version + 1..(1 << next_marker)).enumerate() {
122138
verify_nonexistence::<TC>(
@@ -137,6 +153,23 @@ pub fn key_history_verify<TC: Configuration>(
137153
})?;
138154
}
139155

156+
// Perform checks for expected number of future-marker proofs
157+
let expected_num_future_marker_proofs = final_marker + 1 - next_marker;
158+
if expected_num_future_marker_proofs != proof.future_marker_vrf_proofs.len() as u64 {
159+
return Err(VerificationError::HistoryProof(format!(
160+
"Expected {} future-marker proofs, but got {}",
161+
expected_num_future_marker_proofs,
162+
proof.future_marker_vrf_proofs.len()
163+
)));
164+
}
165+
if proof.future_marker_vrf_proofs.len() != proof.non_existence_of_future_marker_proofs.len() {
166+
return Err(VerificationError::HistoryProof(format!(
167+
"Expected equal number of future-marker proofs, but got ({}, {})",
168+
proof.future_marker_vrf_proofs.len(),
169+
proof.non_existence_of_future_marker_proofs.len()
170+
)));
171+
}
172+
140173
// Verify the VRFs and non-membership proofs for future markers
141174
for (i, pow) in (next_marker..final_marker + 1).enumerate() {
142175
let version = 1 << pow;

0 commit comments

Comments
 (0)