don't transmit precalculated key IDs

fixes #118
diff --git a/src/interchange/mod.rs b/src/interchange/mod.rs
index 470ad25..0f9a090 100644
--- a/src/interchange/mod.rs
+++ b/src/interchange/mod.rs
@@ -116,10 +116,7 @@
 ///   "type": "root",
 ///   "version": NATURAL_NUMBER,
 ///   "expires": EXPIRES,
-///   "keys": {
-///     KEY_ID: PUB_KEY,
-///     ...
-///   },
+///   "keys": [PUB_KEY, ...]
 ///   "root": ROLE_DESCRIPTION,
 ///   "snapshot": ROLE_DESCRIPTION,
 ///   "targets": ROLE_DESCRIPTION,
@@ -132,7 +129,7 @@
 /// ```bash
 /// {
 ///   "threshold": NATURAL_NUMBER,
-///   "key_ids": [KEY_ID]
+///   "key_ids": [KEY_ID, ...]
 /// }
 /// ```
 ///
@@ -189,8 +186,8 @@
 ///   "name": ROLE,
 ///   "threshold": NATURAL_NUMBER,
 ///   "terminating": BOOLEAN,
-///   "key_ids": [KEY_ID],
-///   "paths": [PATH]
+///   "key_ids": [KEY_ID, ...],
+///   "paths": [PATH, ...]
 /// }
 /// ```
 ///
diff --git a/src/metadata.rs b/src/metadata.rs
index eda6908..f0d9677 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -526,7 +526,12 @@
             )));
         }
 
+        let keys_len = keys.len();
         let keys = HashMap::from_iter(keys.drain(..).map(|k| (k.key_id().clone(), k)));
+        
+        if keys.len() != keys_len {
+            return Err(Error::IllegalArgument("Cannot have duplicate keys".into()));
+        }
 
         Ok(RootMetadata {
             version: version,
@@ -1593,45 +1598,43 @@
             "version": 1,
             "expires": "2017-01-01T00:00:00Z",
             "consistent_snapshot": false,
-            "keys": {
-                "qfrfBrkB4lBBSDEBlZgaTGS_SrE6UfmON9kP4i3dJFY=": {
-                    "type": "ed25519",
-                    "public_key": "MCwwBwYDK2VwBQADIQDrisJrXJ7wJ5474-giYqk7zhb\
-                        -WO5CJQDTjK9GHGWjtg==",
-                },
-                "4hsyITLMQoWBg0ldCLKPlRZPIEf258cMg-xdAROsO6o=": {
-                    "type": "ed25519",
-                    "public_key": "MCwwBwYDK2VwBQADIQAWY3bJCn9xfQJwVicvNhwlL7BQ\
-                        vtGgZ_8giaAwL7q3PQ==",
-                },
-                "5WvZhiiSSUung_OhJVbPshKwD_ZNkgeg80i4oy2KAVs=": {
-                    "type": "ed25519",
-                    "public_key": "MCwwBwYDK2VwBQADIQBo2eyzhzcQBajrjmAQUwXDQ1ao_\
-                        NhZ1_7zzCKL8rKzsg==",
-                },
-                "C2hNB7qN99EAbHVGHPIJc5Hqa9RfEilnMqsCNJ5dGdw=": {
+            "keys": [
+                {
                     "type": "ed25519",
                     "public_key": "MCwwBwYDK2VwBQADIQAUEK4wU6pwu_qYQoqHnWTTACo1\
                         ePffquscsHZOhg9-Cw==",
                 },
+                {
+                    "type": "ed25519",
+                    "public_key": "MCwwBwYDK2VwBQADIQDrisJrXJ7wJ5474-giYqk7zhb\
+                        -WO5CJQDTjK9GHGWjtg==",
+                },
+                {
+                    "type": "ed25519",
+                    "public_key": "MCwwBwYDK2VwBQADIQAWY3bJCn9xfQJwVicvNhwlL7BQ\
+                        vtGgZ_8giaAwL7q3PQ==",
+                },
+                {
+                    "type": "ed25519",
+                    "public_key": "MCwwBwYDK2VwBQADIQBo2eyzhzcQBajrjmAQUwXDQ1ao_\
+                        NhZ1_7zzCKL8rKzsg==",
+                },
+            ],
+            "root": {
+                "threshold": 1,
+                "key_ids": ["qfrfBrkB4lBBSDEBlZgaTGS_SrE6UfmON9kP4i3dJFY="],
             },
-            "roles": {
-                "root": {
-                    "threshold": 1,
-                    "key_ids": ["qfrfBrkB4lBBSDEBlZgaTGS_SrE6UfmON9kP4i3dJFY="],
-                },
-                "snapshot": {
-                    "threshold": 1,
-                    "key_ids": ["5WvZhiiSSUung_OhJVbPshKwD_ZNkgeg80i4oy2KAVs="],
-                },
-                "targets": {
-                    "threshold": 1,
-                    "key_ids": ["4hsyITLMQoWBg0ldCLKPlRZPIEf258cMg-xdAROsO6o="],
-                },
-                "timestamp": {
-                    "threshold": 1,
-                    "key_ids": ["C2hNB7qN99EAbHVGHPIJc5Hqa9RfEilnMqsCNJ5dGdw="],
-                },
+            "snapshot": {
+                "threshold": 1,
+                "key_ids": ["5WvZhiiSSUung_OhJVbPshKwD_ZNkgeg80i4oy2KAVs="],
+            },
+            "targets": {
+                "threshold": 1,
+                "key_ids": ["4hsyITLMQoWBg0ldCLKPlRZPIEf258cMg-xdAROsO6o="],
+            },
+            "timestamp": {
+                "threshold": 1,
+                "key_ids": ["C2hNB7qN99EAbHVGHPIJc5Hqa9RfEilnMqsCNJ5dGdw="],
             },
         });
 
@@ -1993,30 +1996,6 @@
         assert!(json::from_value::<RootMetadata>(root_json).is_err());
     }
 
-    // Refuse to deserialize root metadata if any of the defined keys don't match their key ID
-    #[test]
-    fn deserialize_json_root_bad_key_ids() {
-        let mut root_json = make_root();
-        match root_json.as_object_mut() {
-            Some(obj) => {
-                match obj.get_mut("keys").unwrap().as_object_mut() {
-                    Some(keys) => {
-                        let key_id = keys.keys().next().unwrap().clone();
-                        let key = keys.get(&key_id).unwrap().clone();
-                        let mut bytes = BASE64URL.decode(key_id.as_bytes()).unwrap();
-                        bytes[0] ^= 0x01;
-                        let key_id = BASE64URL.encode(&bytes);
-                        let _ = keys.insert(key_id, key);
-                    }
-                    None => panic!(),
-                }
-            }
-            None => panic!(),
-        }
-
-        assert!(json::from_value::<RootMetadata>(root_json).is_err());
-    }
-
     fn set_threshold(value: &mut json::Value, threshold: i32) {
         match value.as_object_mut() {
             Some(obj) => {
diff --git a/src/shims.rs b/src/shims.rs
index 6a9541d..52b4beb 100644
--- a/src/shims.rs
+++ b/src/shims.rs
@@ -15,29 +15,32 @@
     version: u32,
     consistent_snapshot: bool,
     expires: DateTime<Utc>,
-    keys: HashMap<crypto::KeyId, crypto::PublicKey>,
-    roles: HashMap<metadata::Role, metadata::RoleDefinition>,
+    keys: Vec<crypto::PublicKey>,
+    root: metadata::RoleDefinition,
+    snapshot: metadata::RoleDefinition,
+    targets: metadata::RoleDefinition,
+    timestamp: metadata::RoleDefinition,
 }
 
 impl RootMetadata {
     pub fn from(meta: &metadata::RootMetadata) -> Result<Self> {
-        let mut roles = HashMap::new();
-        let _ = roles.insert(metadata::Role::Root, meta.root().clone());
-        let _ = roles.insert(metadata::Role::Snapshot, meta.snapshot().clone());
-        let _ = roles.insert(metadata::Role::Targets, meta.targets().clone());
-        let _ = roles.insert(metadata::Role::Timestamp, meta.timestamp().clone());
+        let mut keys = meta.keys().iter().map(|(_, v)| v.clone()).collect::<Vec<crypto::PublicKey>>();
+        keys.sort_by_key(|k| k.key_id().clone());
 
         Ok(RootMetadata {
             typ: metadata::Role::Root,
             version: meta.version(),
             expires: meta.expires().clone(),
             consistent_snapshot: meta.consistent_snapshot(),
-            keys: meta.keys().clone(),
-            roles: roles,
+            keys: keys,
+            root: meta.root().clone(),
+            snapshot: meta.snapshot().clone(),
+            targets: meta.targets().clone(),
+            timestamp: meta.timestamp().clone(),
         })
     }
 
-    pub fn try_into(mut self) -> Result<metadata::RootMetadata> {
+    pub fn try_into(self) -> Result<metadata::RootMetadata> {
         if self.typ != metadata::Role::Root {
             return Err(Error::Encoding(format!(
                 "Attempted to decode root metdata labeled as {:?}",
@@ -45,50 +48,15 @@
             )));
         }
 
-        let mut keys = Vec::new();
-        for (key_id, value) in self.keys.drain() {
-            if &key_id != value.key_id() {
-                return Err(Error::Encoding(format!(
-                    "Received key with ID {:?} but calculated it's value as {:?}. \
-                       Refusing to add it to the set of trusted keys.",
-                    key_id,
-                    value.key_id()
-                )));
-            } else {
-                debug!(
-                    "Found key with good ID {:?}. Adding it to the set of trusted keys.",
-                    key_id
-                );
-                keys.push(value);
-            }
-        }
-
-        let root = self.roles.remove(&metadata::Role::Root).ok_or_else(|| {
-            Error::Encoding("Missing root role definition".into())
-        })?;
-        let snapshot = self.roles.remove(&metadata::Role::Snapshot).ok_or_else(
-            || {
-                Error::Encoding("Missing snapshot role definition".into())
-            },
-        )?;
-        let targets = self.roles.remove(&metadata::Role::Targets).ok_or_else(|| {
-            Error::Encoding("Missing targets role definition".into())
-        })?;
-        let timestamp = self.roles.remove(&metadata::Role::Timestamp).ok_or_else(
-            || {
-                Error::Encoding("Missing timestamp role definition".into())
-            },
-        )?;
-
         metadata::RootMetadata::new(
             self.version,
             self.expires,
             self.consistent_snapshot,
-            keys,
-            root,
-            snapshot,
-            targets,
-            timestamp,
+            self.keys,
+            self.root,
+            self.snapshot,
+            self.targets,
+            self.timestamp,
         )
     }
 }