Skip to content

Commit 8d8d0d5

Browse files
Merge #95
95: fix: enforce that root key signatures are needed if root keys are set r=mfontanini a=mfontanini This is a port of NillionNetwork/nuc-ts#35 which enforces the root key signature is required. Co-authored-by: Matias Fontanini <[email protected]>
2 parents 8d75590 + 9a3928a commit 8d8d0d5

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

libs/nucs/src/validator.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,13 @@ impl NucValidator {
148148

149149
// Validations applied to proofs
150150
fn validate_proofs(proofs: &[&NucToken], root_keys: &HashSet<Box<[u8]>>) -> ValidationResult {
151-
if let Some(proof) = proofs.last() {
152-
if !root_keys.contains(proof.issuer.public_key.as_slice()) {
153-
return Err(ValidationError::Validation(ValidationKind::RootKeySignatureMissing));
154-
}
151+
let contains_root_signature = match proofs.last() {
152+
Some(proof) => root_keys.contains(proof.issuer.public_key.as_slice()),
153+
// if there's no proof but also no root keys we don't need one.
154+
None => root_keys.is_empty(),
155+
};
156+
if !contains_root_signature {
157+
return Err(ValidationError::Validation(ValidationKind::RootKeySignatureMissing));
155158
}
156159

157160
for proof in proofs {
@@ -459,11 +462,12 @@ mod tests {
459462

460463
struct Asserter {
461464
parameters: ValidationParameters,
465+
root_keys: Vec<PublicKey>,
462466
}
463467

464468
impl Asserter {
465469
fn new(parameters: ValidationParameters) -> Self {
466-
Self { parameters }
470+
Self { parameters, root_keys: ROOT_PUBLIC_KEYS.clone() }
467471
}
468472

469473
fn log_tokens(envelope: &NucTokenEnvelope) {
@@ -479,7 +483,7 @@ mod tests {
479483
Self::log_tokens(&envelope);
480484

481485
let expected_failure = expected_failure.into();
482-
match NucValidator::new(&ROOT_PUBLIC_KEYS).validate(envelope, self.parameters) {
486+
match NucValidator::new(&self.root_keys).validate(envelope, self.parameters) {
483487
Ok(_) => panic!("validation succeeded"),
484488
Err(e) if e.to_string() == expected_failure.to_string() => (),
485489
Err(e) => panic!("unexpected type of failure: {e}"),
@@ -488,14 +492,14 @@ mod tests {
488492

489493
fn assert_success(self, envelope: NucTokenEnvelope) -> ValidatedNucToken {
490494
Self::log_tokens(&envelope);
491-
NucValidator::new(&ROOT_PUBLIC_KEYS).validate(envelope, self.parameters).expect("validation failed")
495+
NucValidator::new(&self.root_keys).validate(envelope, self.parameters).expect("validation failed")
492496
}
493497
}
494498

495499
impl Default for Asserter {
496500
fn default() -> Self {
497501
let parameters = ValidationParameters::default();
498-
Self { parameters }
502+
Self::new(parameters)
499503
}
500504
}
501505

@@ -662,14 +666,17 @@ mod tests {
662666
let token = Chainer::default().chain([root]).encode();
663667
let (base, signature) = token.rsplit_once(".").unwrap();
664668

665-
// Change every byte in the signature and make sure validation fails every time.
669+
// Change a byte in the signature
666670
let signature = from_base64(signature).unwrap();
667671
let mut signature = signature.clone();
668672
signature[0] ^= 1;
669673
let signature = to_base64(&signature);
670674
let token = format!("{base}.{signature}");
671675
let envelope = NucTokenEnvelope::decode(&token).expect("decode failed");
672-
Asserter::default().assert_failure(envelope, ValidationKind::InvalidSignatures);
676+
let mut asserter = Asserter::default();
677+
// Don't require a root key signature
678+
asserter.root_keys = Vec::new();
679+
asserter.assert_failure(envelope, ValidationKind::InvalidSignatures);
673680
}
674681

675682
#[test]
@@ -968,4 +975,20 @@ mod tests {
968975
};
969976
Asserter::new(parameters).assert_success(envelope);
970977
}
978+
979+
#[test]
980+
fn valid_no_root_keys_needed() {
981+
let subject_key = SecretKey::random(&mut rand::thread_rng());
982+
let subject = Did::from_secret_key(&subject_key);
983+
let token = NucTokenBuilder::delegation([])
984+
.subject(subject.clone())
985+
.audience(subject)
986+
.command(["nil"])
987+
.issued_by(subject_key);
988+
989+
let envelope = Chainer::default().chain([token]);
990+
let mut asserter = Asserter::default();
991+
asserter.root_keys = Vec::new();
992+
asserter.assert_success(envelope);
993+
}
971994
}

0 commit comments

Comments
 (0)