don't use default hash algorithms, let implementer decide
fixes #106
diff --git a/src/interchange/cjson.rs b/src/interchange/cjson.rs
index daff772..d06a31e 100644
--- a/src/interchange/cjson.rs
+++ b/src/interchange/cjson.rs
@@ -37,8 +37,7 @@
&Value::String(ref s) => {
// this mess is abusing serde_json to get json escaping
let s = json::Value::String(s.clone());
- let s = json::to_string(&s)
- .map_err(|e| format!("{:?}", e))?;
+ let s = json::to_string(&s).map_err(|e| format!("{:?}", e))?;
Ok(buf.extend(s.as_bytes()))
}
&Value::Array(ref arr) => {
@@ -61,11 +60,10 @@
buf.push(b',');
}
first = false;
-
+
// this mess is abusing serde_json to get json escaping
let k = json::Value::String(k.clone());
- let k = json::to_string(&k)
- .map_err(|e| format!("{:?}", e))?;
+ let k = json::to_string(&k).map_err(|e| format!("{:?}", e))?;
buf.extend(k.as_bytes());
buf.push(b':');
diff --git a/src/metadata.rs b/src/metadata.rs
index 341ab85..e6662b6 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -927,29 +927,41 @@
///
/// fn main() {
/// let bytes: &[u8] = b"it was a pleasure to burn";
- /// let target_description = TargetDescription::from_reader(bytes).unwrap();
///
/// // $ printf 'it was a pleasure to burn' | sha256sum
/// let s = "Rd9zlbzrdWfeL7gnIEi05X-Yv2TCpy4qqZM1N72ZWQs=";
/// let sha256 = HashValue::new(BASE64URL.decode(s.as_bytes()).unwrap());
///
+ /// let target_description =
+ /// TargetDescription::from_reader(bytes, &[HashAlgorithm::Sha256]).unwrap();
+ /// assert_eq!(target_description.length(), bytes.len() as u64);
+ /// assert_eq!(target_description.hashes().get(&HashAlgorithm::Sha256), Some(&sha256));
+ ///
/// // $ printf 'it was a pleasure to burn' | sha512sum
/// let s ="tuIxwKybYdvJpWuUj6dubvpwhkAozWB6hMJIRzqn2jOUdtDTBg381brV4K\
/// BU1zKP8GShoJuXEtCf5NkDTCEJgQ==";
/// let sha512 = HashValue::new(BASE64URL.decode(s.as_bytes()).unwrap());
///
+ /// let target_description =
+ /// TargetDescription::from_reader(bytes, &[HashAlgorithm::Sha512]).unwrap();
/// assert_eq!(target_description.length(), bytes.len() as u64);
- /// assert_eq!(target_description.hashes().get(&HashAlgorithm::Sha256), Some(&sha256));
/// assert_eq!(target_description.hashes().get(&HashAlgorithm::Sha512), Some(&sha512));
/// }
/// ```
- pub fn from_reader<R>(mut read: R) -> Result<Self>
+ pub fn from_reader<R>(mut read: R, hash_algs: &[HashAlgorithm]) -> Result<Self>
where
R: Read,
{
let mut length = 0;
- let mut sha256 = digest::Context::new(&SHA256);
- let mut sha512 = digest::Context::new(&SHA512);
+ let mut hashes = HashMap::new();
+ for alg in hash_algs {
+ let context = match alg {
+ &HashAlgorithm::Sha256 => digest::Context::new(&SHA256),
+ &HashAlgorithm::Sha512 => digest::Context::new(&SHA512),
+ };
+
+ let _ = hashes.insert(alg, context);
+ }
let mut buf = vec![0; 1024];
loop {
@@ -960,22 +972,22 @@
}
length += read_bytes as u64;
- sha256.update(&buf[0..read_bytes]);
- sha512.update(&buf[0..read_bytes]);
+
+ for (_, mut context) in hashes.iter_mut() {
+ context.update(&buf[0..read_bytes]);
+ }
}
e @ Err(_) => e.map(|_| ())?,
}
}
- let mut hashes = HashMap::new();
- let _ = hashes.insert(
- HashAlgorithm::Sha256,
- HashValue::new(sha256.finish().as_ref().to_vec()),
- );
- let _ = hashes.insert(
- HashAlgorithm::Sha512,
- HashValue::new(sha512.finish().as_ref().to_vec()),
- );
+ let hashes = hashes
+ .drain()
+ .map(|(k, v)| {
+ (k.clone(), HashValue::new(v.finish().as_ref().to_vec()))
+ })
+ .collect();
+
Ok(TargetDescription {
length: length,
hashes: hashes,
@@ -1297,14 +1309,12 @@
#[test]
fn serde_target_description() {
let s: &[u8] = b"from water does all life begin";
- let description = TargetDescription::from_reader(s).unwrap();
+ let description = TargetDescription::from_reader(s, &[HashAlgorithm::Sha256]).unwrap();
let jsn_str = json::to_string(&description).unwrap();
let jsn = json!({
"length": 30,
"hashes": {
"sha256": "_F10XHEryG6poxJk2sDJVu61OFf2d-7QWCm7cQE8rhg=",
- "sha512": "593J2T34bimKdKT5MmaSZ0tXvmj13EVdpTGK5p2E2R3ife-xxZ8Ql\
- EHsezz8HeN1_Y0SJqvLfK2WKUZQc98R_A==",
},
});
let parsed_str: TargetDescription = json::from_str(&jsn_str).unwrap();
@@ -1496,7 +1506,7 @@
Utc.ymd(2017, 1, 1).and_hms(0, 0, 0),
hashmap! {
TargetPath::new("foo".into()).unwrap() =>
- TargetDescription::from_reader(b"foo" as &[u8]).unwrap(),
+ TargetDescription::from_reader(b"foo" as &[u8], &[HashAlgorithm::Sha256]).unwrap(),
},
None,
).unwrap();
@@ -1510,8 +1520,6 @@
"length": 3,
"hashes": {
"sha256": "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564=",
- "sha512": "9_u6bgY2-JDlb7vzKD5STG-jIErimDgtYkdB0NxmODJuKCx\
- Bvl5CVNiCB3LFUYosWowMf37aGVlKfrU5RT4e1w==",
},
},
},
diff --git a/src/repository.rs b/src/repository.rs
index a0c6866..6e5808f 100644
--- a/src/repository.rs
+++ b/src/repository.rs
@@ -307,7 +307,7 @@
D: DataInterchange,
{
/// Create a new repository with the given `Url` and `Client`. Callers *should* include a
- /// custom User-Agent prefix to maintainers of TUF repositories keep track of which client
+ /// custom User-Agent prefix to help maintainers of TUF repositories keep track of which client
/// versions exist in the field.
pub fn new(url: Url, client: Client, user_agent_prefix: Option<String>) -> Self {
let user_agent = match user_agent_prefix {
@@ -536,8 +536,8 @@
repo.initialize().expect("initialize repo");
let data: &[u8] = b"like tears in the rain";
- let target_description =
- TargetDescription::from_reader(data).expect("generate target description");
+ let target_description = TargetDescription::from_reader(data, &[HashAlgorithm::Sha256])
+ .expect("generate target description");
let path = TargetPath::new("batty".into()).expect("make target path");
repo.store_target(data, &path, &target_description).expect(
"store target",
@@ -568,8 +568,8 @@
repo.initialize().expect("initialize repo");
let data: &[u8] = b"like tears in the rain";
- let target_description =
- TargetDescription::from_reader(data).expect("generate target desert");
+ let target_description = TargetDescription::from_reader(data, &[HashAlgorithm::Sha256])
+ .expect("generate target desert");
let path = TargetPath::new("batty".into()).expect("make target path");
repo.store_target(data, &path, &target_description).expect(
"store target",
diff --git a/tests/integration.rs b/tests/integration.rs
index 8c82754..1c57fa7 100644
--- a/tests/integration.rs
+++ b/tests/integration.rs
@@ -5,7 +5,7 @@
use chrono::offset::Utc;
use std::collections::{HashSet, HashMap};
use tuf::Tuf;
-use tuf::crypto::{PrivateKey, SignatureScheme};
+use tuf::crypto::{PrivateKey, SignatureScheme, HashAlgorithm};
use tuf::interchange::JsonDataInterchange;
use tuf::metadata::{RoleDefinition, RootMetadata, MetadataPath, SignedMetadata, TargetDescription,
TargetPath, TargetsMetadata, MetadataDescription, SnapshotMetadata,
@@ -142,7 +142,8 @@
//// build the delegation ////
let target_file: &[u8] = b"bar";
let target_path = TargetPath::new("foo".into()).unwrap();
- let target_description = TargetDescription::from_reader(target_file).unwrap();
+ let target_description = TargetDescription::from_reader(target_file, &[HashAlgorithm::Sha256])
+ .unwrap();
let mut target_map = HashMap::new();
let _ = target_map.insert(target_path, target_description);
@@ -332,7 +333,8 @@
//// build delegation B ////
let target_file: &[u8] = b"bar";
let target_path = TargetPath::new("foo".into()).unwrap();
- let target_description = TargetDescription::from_reader(target_file).unwrap();
+ let target_description = TargetDescription::from_reader(target_file, &[HashAlgorithm::Sha256])
+ .unwrap();
let mut target_map = HashMap::new();
let _ = target_map.insert(target_path, target_description);
diff --git a/tests/simple_example.rs b/tests/simple_example.rs
index 6e63325..76f24ea 100644
--- a/tests/simple_example.rs
+++ b/tests/simple_example.rs
@@ -6,7 +6,7 @@
use std::collections::{HashSet, HashMap};
use tuf::{Tuf, Error};
use tuf::client::{Client, Config};
-use tuf::crypto::{PrivateKey, SignatureScheme, KeyId};
+use tuf::crypto::{PrivateKey, SignatureScheme, KeyId, HashAlgorithm};
use tuf::interchange::JsonDataInterchange;
use tuf::metadata::{RoleDefinition, RootMetadata, Role, MetadataVersion, MetadataPath,
SignedMetadata, TargetDescription, TargetPath, TargetsMetadata,
@@ -117,7 +117,7 @@
let target_file: &[u8] = b"things fade, alternatives exclude";
let target_path = TargetPath::new("grendel".into())?;
- let target_description = TargetDescription::from_reader(target_file)?;
+ let target_description = TargetDescription::from_reader(target_file, &[HashAlgorithm::Sha256])?;
let _ = remote.store_target(target_file, &target_path, &target_description);
let mut target_map = HashMap::new();