mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
hashes, ecaps2, jingle_ft: Make the algorithm a proper enum.
This commit is contained in:
parent
4ec92b16ac
commit
b22acff15e
3 changed files with 116 additions and 61 deletions
|
@ -8,7 +8,7 @@ use std::convert::TryFrom;
|
||||||
|
|
||||||
use disco::{Feature, Identity, Disco};
|
use disco::{Feature, Identity, Disco};
|
||||||
use data_forms::DataForm;
|
use data_forms::DataForm;
|
||||||
use hashes::Hash;
|
use hashes::{Hash, Algo};
|
||||||
|
|
||||||
use minidom::Element;
|
use minidom::Element;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
@ -118,49 +118,52 @@ pub fn compute_disco(disco: &Disco) -> Vec<u8> {
|
||||||
final_string
|
final_string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make algo into an enum.
|
pub fn hash_ecaps2(data: &[u8], algo: Algo) -> Result<Hash, String> {
|
||||||
pub fn hash_ecaps2(data: &[u8], algo: &str) -> String {
|
Ok(Hash {
|
||||||
match algo {
|
algo: algo.clone(),
|
||||||
"sha-256" => {
|
hash: match algo {
|
||||||
|
Algo::Sha_256 => {
|
||||||
let mut hasher = Sha256::default();
|
let mut hasher = Sha256::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let hash = hasher.result();
|
let hash = hasher.result();
|
||||||
base64::encode(&hash.as_slice())
|
base64::encode(&hash.as_slice())
|
||||||
},
|
},
|
||||||
"sha-512" => {
|
Algo::Sha_512 => {
|
||||||
let mut hasher = Sha512::default();
|
let mut hasher = Sha512::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let hash = hasher.result();
|
let hash = hasher.result();
|
||||||
base64::encode(&hash.as_slice())
|
base64::encode(&hash.as_slice())
|
||||||
},
|
},
|
||||||
"sha3-256" => {
|
Algo::Sha3_256 => {
|
||||||
let mut hasher = Sha3_256::default();
|
let mut hasher = Sha3_256::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let hash = hasher.result();
|
let hash = hasher.result();
|
||||||
base64::encode(&hash.as_slice())
|
base64::encode(&hash.as_slice())
|
||||||
},
|
},
|
||||||
"sha3-512" => {
|
Algo::Sha3_512 => {
|
||||||
let mut hasher = Sha3_512::default();
|
let mut hasher = Sha3_512::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let hash = hasher.result();
|
let hash = hasher.result();
|
||||||
base64::encode(&hash.as_slice())
|
base64::encode(&hash.as_slice())
|
||||||
},
|
},
|
||||||
"blake2b-256" => {
|
Algo::Blake2b_256 => {
|
||||||
let mut hasher = Blake2b::default();
|
let mut hasher = Blake2b::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let mut buf: [u8; 32] = [0; 32];
|
let mut buf: [u8; 32] = [0; 32];
|
||||||
let hash = hasher.variable_result(&mut buf).unwrap();
|
let hash = hasher.variable_result(&mut buf).unwrap();
|
||||||
base64::encode(hash)
|
base64::encode(hash)
|
||||||
},
|
},
|
||||||
"blake2b-512" => {
|
Algo::Blake2b_512 => {
|
||||||
let mut hasher = Blake2b::default();
|
let mut hasher = Blake2b::default();
|
||||||
hasher.input(data);
|
hasher.input(data);
|
||||||
let mut buf: [u8; 64] = [0; 64];
|
let mut buf: [u8; 64] = [0; 64];
|
||||||
let hash = hasher.variable_result(&mut buf).unwrap();
|
let hash = hasher.variable_result(&mut buf).unwrap();
|
||||||
base64::encode(hash)
|
base64::encode(hash)
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
Algo::Sha_1 => return Err(String::from("Disabled algorithm sha-1: unsafe.")),
|
||||||
}
|
Algo::Unknown(algo) => return Err(format!("Unknown algorithm: {}.", algo)),
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -174,9 +177,9 @@ mod tests {
|
||||||
let elem: Element = "<c xmlns='urn:xmpp:caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash><hash xmlns='urn:xmpp:hashes:2' algo='sha3-256'>+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=</hash></c>".parse().unwrap();
|
let elem: Element = "<c xmlns='urn:xmpp:caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash><hash xmlns='urn:xmpp:hashes:2' algo='sha3-256'>+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=</hash></c>".parse().unwrap();
|
||||||
let ecaps2 = ECaps2::try_from(&elem).unwrap();
|
let ecaps2 = ECaps2::try_from(&elem).unwrap();
|
||||||
assert_eq!(ecaps2.hashes.len(), 2);
|
assert_eq!(ecaps2.hashes.len(), 2);
|
||||||
assert_eq!(ecaps2.hashes[0].algo, "sha-256");
|
assert_eq!(ecaps2.hashes[0].algo, Algo::Sha_256);
|
||||||
assert_eq!(ecaps2.hashes[0].hash, "K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=");
|
assert_eq!(ecaps2.hashes[0].hash, "K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=");
|
||||||
assert_eq!(ecaps2.hashes[1].algo, "sha3-256");
|
assert_eq!(ecaps2.hashes[1].algo, Algo::Sha3_256);
|
||||||
assert_eq!(ecaps2.hashes[1].hash, "+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=");
|
assert_eq!(ecaps2.hashes[1].hash, "+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,10 +265,10 @@ mod tests {
|
||||||
assert_eq!(ecaps2.len(), 0x1d9);
|
assert_eq!(ecaps2.len(), 0x1d9);
|
||||||
assert_eq!(ecaps2, expected);
|
assert_eq!(ecaps2, expected);
|
||||||
|
|
||||||
let sha_256 = ecaps2::hash_ecaps2(&ecaps2, "sha-256");
|
let sha_256 = ecaps2::hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
|
||||||
assert_eq!(sha_256, "kzBZbkqJ3ADrj7v08reD1qcWUwNGHaidNUgD7nHpiw8=");
|
assert_eq!(sha_256.hash, "kzBZbkqJ3ADrj7v08reD1qcWUwNGHaidNUgD7nHpiw8=");
|
||||||
let sha3_256 = ecaps2::hash_ecaps2(&ecaps2, "sha3-256");
|
let sha3_256 = ecaps2::hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
|
||||||
assert_eq!(sha3_256, "79mdYAfU9rEdTOcWDO7UEAt6E56SUzk/g6TnqUeuD9Q=");
|
assert_eq!(sha3_256.hash, "79mdYAfU9rEdTOcWDO7UEAt6E56SUzk/g6TnqUeuD9Q=");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -434,15 +437,15 @@ mod tests {
|
||||||
assert_eq!(ecaps2.len(), 0x543);
|
assert_eq!(ecaps2.len(), 0x543);
|
||||||
assert_eq!(ecaps2, expected);
|
assert_eq!(ecaps2, expected);
|
||||||
|
|
||||||
let sha_256 = ecaps2::hash_ecaps2(&ecaps2, "sha-256");
|
let sha_256 = ecaps2::hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
|
||||||
assert_eq!(sha_256, "u79ZroNJbdSWhdSp311mddz44oHHPsEBntQ5b1jqBSY=");
|
assert_eq!(sha_256.hash, "u79ZroNJbdSWhdSp311mddz44oHHPsEBntQ5b1jqBSY=");
|
||||||
let sha3_256 = ecaps2::hash_ecaps2(&ecaps2, "sha3-256");
|
let sha3_256 = ecaps2::hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
|
||||||
assert_eq!(sha3_256, "XpUJzLAc93258sMECZ3FJpebkzuyNXDzRNwQog8eycg=");
|
assert_eq!(sha3_256.hash, "XpUJzLAc93258sMECZ3FJpebkzuyNXDzRNwQog8eycg=");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blake2b_512() {
|
fn test_blake2b_512() {
|
||||||
let hash = ecaps2::hash_ecaps2("abc".as_bytes(), "blake2b-512");
|
let hash = ecaps2::hash_ecaps2("abc".as_bytes(), Algo::Blake2b_512).unwrap();
|
||||||
let known_hash: Vec<u8> = vec!(
|
let known_hash: Vec<u8> = vec!(
|
||||||
0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D, 0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12, 0xF6, 0xE9,
|
0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D, 0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12, 0xF6, 0xE9,
|
||||||
0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7, 0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1,
|
0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7, 0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1,
|
||||||
|
@ -450,6 +453,6 @@ mod tests {
|
||||||
0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A, 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23,
|
0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A, 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23,
|
||||||
);
|
);
|
||||||
let known_hash = base64::encode(&known_hash);
|
let known_hash = base64::encode(&known_hash);
|
||||||
assert_eq!(hash, known_hash);
|
assert_eq!(hash.hash, known_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,64 @@
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use minidom::Element;
|
use minidom::{Element, IntoAttributeValue};
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
use ns;
|
use ns;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Algo {
|
||||||
|
Sha_1,
|
||||||
|
Sha_256,
|
||||||
|
Sha_512,
|
||||||
|
Sha3_256,
|
||||||
|
Sha3_512,
|
||||||
|
Blake2b_256,
|
||||||
|
Blake2b_512,
|
||||||
|
Unknown(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Algo {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Algo, Error> {
|
||||||
|
Ok(match s {
|
||||||
|
"" => return Err(Error::ParseError("'algo' argument can’t be empty.")),
|
||||||
|
|
||||||
|
"sha-1" => Algo::Sha_1,
|
||||||
|
"sha-256" => Algo::Sha_256,
|
||||||
|
"sha-512" => Algo::Sha_512,
|
||||||
|
"sha3-256" => Algo::Sha3_256,
|
||||||
|
"sha3-512" => Algo::Sha3_512,
|
||||||
|
"blake2b-256" => Algo::Blake2b_256,
|
||||||
|
"blake2b-512" => Algo::Blake2b_512,
|
||||||
|
value => Algo::Unknown(value.to_owned()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoAttributeValue for Algo {
|
||||||
|
fn into_attribute_value(self) -> Option<String> {
|
||||||
|
Some(String::from(match self {
|
||||||
|
Algo::Sha_1 => "sha-1",
|
||||||
|
Algo::Sha_256 => "sha-256",
|
||||||
|
Algo::Sha_512 => "sha-512",
|
||||||
|
Algo::Sha3_256 => "sha3-256",
|
||||||
|
Algo::Sha3_512 => "sha3-512",
|
||||||
|
Algo::Blake2b_256 => "blake2b-256",
|
||||||
|
Algo::Blake2b_512 => "blake2b-512",
|
||||||
|
Algo::Unknown(text) => return Some(text),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Hash {
|
pub struct Hash {
|
||||||
pub algo: String,
|
pub algo: Algo,
|
||||||
pub hash: String,
|
pub hash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +76,10 @@ impl<'a> TryFrom<&'a Element> for Hash {
|
||||||
for _ in elem.children() {
|
for _ in elem.children() {
|
||||||
return Err(Error::ParseError("Unknown child in hash element."));
|
return Err(Error::ParseError("Unknown child in hash element."));
|
||||||
}
|
}
|
||||||
let algo = elem.attr("algo").ok_or(Error::ParseError("Mandatory argument 'algo' not present in hash element."))?.to_owned();
|
let algo = match elem.attr("algo") {
|
||||||
|
None => Err(Error::ParseError("Mandatory argument 'algo' not present in hash element.")),
|
||||||
|
Some(text) => Algo::from_str(text),
|
||||||
|
}?;
|
||||||
let hash = match elem.text().as_ref() {
|
let hash = match elem.text().as_ref() {
|
||||||
"" => return Err(Error::ParseError("Hash element shouldn’t be empty.")),
|
"" => return Err(Error::ParseError("Hash element shouldn’t be empty.")),
|
||||||
text => text.to_owned(),
|
text => text.to_owned(),
|
||||||
|
@ -58,7 +109,7 @@ mod tests {
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
let elem: Element = "<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=</hash>".parse().unwrap();
|
let elem: Element = "<hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=</hash>".parse().unwrap();
|
||||||
let hash = Hash::try_from(&elem).unwrap();
|
let hash = Hash::try_from(&elem).unwrap();
|
||||||
assert_eq!(hash.algo, "sha-256");
|
assert_eq!(hash.algo, Algo::Sha_256);
|
||||||
assert_eq!(hash.hash, "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=");
|
assert_eq!(hash.hash, "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,6 +238,7 @@ impl<'a> Into<Element> for &'a Description {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use hashes::Algo;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_description() {
|
fn test_description() {
|
||||||
|
@ -261,7 +262,7 @@ mod tests {
|
||||||
assert_eq!(desc.file.date, Some(String::from("2015-07-26T21:46:00")));
|
assert_eq!(desc.file.date, Some(String::from("2015-07-26T21:46:00")));
|
||||||
assert_eq!(desc.file.size, Some(6144u64));
|
assert_eq!(desc.file.size, Some(6144u64));
|
||||||
assert_eq!(desc.file.range, None);
|
assert_eq!(desc.file.range, None);
|
||||||
assert_eq!(desc.file.hashes[0].algo, "sha-1");
|
assert_eq!(desc.file.hashes[0].algo, Algo::Sha_1);
|
||||||
assert_eq!(desc.file.hashes[0].hash, "w0mcJylzCn+AfvuGdqkty2+KP48=");
|
assert_eq!(desc.file.hashes[0].hash, "w0mcJylzCn+AfvuGdqkty2+KP48=");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +284,7 @@ mod tests {
|
||||||
assert_eq!(desc.file.date, None);
|
assert_eq!(desc.file.date, None);
|
||||||
assert_eq!(desc.file.size, None);
|
assert_eq!(desc.file.size, None);
|
||||||
assert_eq!(desc.file.range, None);
|
assert_eq!(desc.file.range, None);
|
||||||
assert_eq!(desc.file.hashes[0].algo, "sha-1");
|
assert_eq!(desc.file.hashes[0].algo, Algo::Sha_1);
|
||||||
assert_eq!(desc.file.hashes[0].hash, "w0mcJylzCn+AfvuGdqkty2+KP48=");
|
assert_eq!(desc.file.hashes[0].hash, "w0mcJylzCn+AfvuGdqkty2+KP48=");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue