From f2716a0d26a7fd197b14fbb143efd3c76cd79993 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 14 Jun 2019 11:27:40 +0200 Subject: [PATCH] add hex_to_digest and digest_to_hex --- proxmox-tools/Cargo.toml | 1 + proxmox-tools/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/proxmox-tools/Cargo.toml b/proxmox-tools/Cargo.toml index 7de28a8a..b8ea6530 100644 --- a/proxmox-tools/Cargo.toml +++ b/proxmox-tools/Cargo.toml @@ -11,6 +11,7 @@ authors = [ endian_trait = { version = "0.6", features = ["arrays"] } libc = "0.2" valgrind_request = { version = "1.1.0", optional = true } +failure = "0.1" [features] default = [ "valgrind" ] diff --git a/proxmox-tools/src/lib.rs b/proxmox-tools/src/lib.rs index 1d3cc27b..e50f3039 100644 --- a/proxmox-tools/src/lib.rs +++ b/proxmox-tools/src/lib.rs @@ -1,5 +1,7 @@ //! This is a general utility crate used by all our rust projects. +use failure::*; + pub mod io; pub mod vec; @@ -10,3 +12,44 @@ macro_rules! offsetof { unsafe { &(*(0 as *const $ty)).$field as *const _ as usize } } } + +const HEX_CHARS: &'static [u8; 16] = b"0123456789abcdef"; + +pub fn digest_to_hex(digest: &[u8]) -> String { + let mut buf = Vec::::with_capacity(digest.len()*2); + + for i in 0..digest.len() { + buf.push(HEX_CHARS[(digest[i] >> 4) as usize]); + buf.push(HEX_CHARS[(digest[i] & 0xf) as usize]); + } + + unsafe { String::from_utf8_unchecked(buf) } +} + +pub fn hex_to_digest(hex: &str) -> Result<[u8; 32], Error> { + let mut digest = [0u8; 32]; + + let bytes = hex.as_bytes(); + + if bytes.len() != 64 { bail!("got wrong digest length."); } + + let val = |c| { + if c >= b'0' && c <= b'9' { return Ok(c - b'0'); } + if c >= b'a' && c <= b'f' { return Ok(c - b'a' + 10); } + if c >= b'A' && c <= b'F' { return Ok(c - b'A' + 10); } + bail!("found illegal hex character."); + }; + + let mut pos = 0; + for pair in bytes.chunks(2) { + if pos >= digest.len() { bail!("hex digest too long."); } + let h = val(pair[0])?; + let l = val(pair[1])?; + digest[pos] = (h<<4)|l; + pos +=1; + } + + if pos != digest.len() { bail!("hex digest too short."); } + + Ok(digest) +}