root verification
diff --git a/src/error.rs b/src/error.rs
index d11b616..09a40d4 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -21,6 +21,7 @@
UnsupportedKeyFormat(String),
UnsupportedKeyType(String),
UnsupportedSignatureScheme(String),
+ VerificationFailure(String),
}
impl From<json::error::Error> for Error {
diff --git a/src/metadata/metadata.rs b/src/metadata/metadata.rs
index 031de51..a0d9d6d 100644
--- a/src/metadata/metadata.rs
+++ b/src/metadata/metadata.rs
@@ -180,14 +180,22 @@
#[derive(Debug, Serialize, Deserialize)]
pub struct Signature {
key_id: KeyId,
- method: SignatureScheme,
- sig: SignatureValue,
+ scheme: SignatureScheme,
+ signature: SignatureValue,
}
impl Signature {
pub fn key_id(&self) -> &KeyId {
&self.key_id
}
+
+ pub fn scheme(&self) -> &SignatureScheme {
+ &self.scheme
+ }
+
+ pub fn signature(&self) -> &SignatureValue {
+ &self.signature
+ }
}
/// A `KeyId` is calculated as `sha256(public_key_bytes)`. The TUF spec says that it should be
diff --git a/src/tuf.rs b/src/tuf.rs
index b140000..425b432 100644
--- a/src/tuf.rs
+++ b/src/tuf.rs
@@ -8,6 +8,7 @@
#[derive(Debug)]
pub struct Tuf<D: DataInterchange, R: RawData<D>> {
+ root: RootMetadata,
_raw_data: PhantomData<R>,
_interchange: PhantomData<D>,
}
@@ -20,19 +21,54 @@
signed_root.signatures_mut().retain(|s| {
root_key_ids.contains(s.key_id())
});
- let canonical_bytes = signed_root.signed().canonicalize()?;
-
- let mut valid = 0;
- for sig in signed_root.signatures() {
-
- }
-
- let root = signed_root.signed().deserialize::<RootMetadata>()?;
-
- panic!() // TODO
+ Self::from_root(signed_root)
}
pub fn from_root(signed_root: SignedMetadata<D, R, RootMetadata>) -> Result<Self, Error> {
- panic!() // TODO
+ if signed_root.signatures().len() < 1 {
+ return Err(Error::VerificationFailure(
+ "The root metadata was not signed with any authorized keys.".into()))
+ }
+
+ let canonical_bytes = signed_root.signed().canonicalize()?;
+ let root = signed_root.signed().deserialize::<RootMetadata>()?;
+
+ let mut signatures_needed = root.root().threshold();
+ if signatures_needed < 1 {
+ return Err(Error::VerificationFailure("Threshold must be strictly greater than zero".into()))
+ }
+
+ for sig in signed_root.signatures() {
+ if !root.root().key_ids().contains(sig.key_id()) {
+ warn!("Key ID {:?} is not authorized to sign root metadata.", sig.key_id());
+ continue
+ }
+
+ match root.keys().get(sig.key_id()) {
+ Some(ref pub_key) => {
+ match pub_key.verify(sig.scheme(), &canonical_bytes, sig.signature()) {
+ Ok(()) => {
+ debug!("Good signature from key ID {:?}", pub_key.key_id());
+ signatures_needed -= 1;
+ },
+ Err(e) => {
+ warn!("Bad signature from key ID {:?}", pub_key.key_id());
+ },
+ }
+ },
+ None => {
+ warn!("Key ID {:?} was not found in the set of available keys.", sig.key_id());
+ }
+ }
+ if signatures_needed == 0 {
+ break
+ }
+ }
+
+ Ok(Tuf {
+ root: root,
+ _raw_data: PhantomData,
+ _interchange: PhantomData,
+ })
}
}