mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-24 08:03:31 +00:00
tools: refactor hex parsing
deduplicate parsing into a `hex_to_bin_exact` Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
46c71f7da3
commit
08d6e20c63
@ -139,6 +139,37 @@ pub fn bin_to_hex(digest: &[u8]) -> String {
|
|||||||
AsHex(digest).to_string()
|
AsHex(digest).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert an ascii character into a hex nibble.
|
||||||
|
fn hex_nibble_to_byte(b: u8) -> Result<u8, Error> {
|
||||||
|
Ok(match b {
|
||||||
|
b'0'..=b'9' => b - b'0',
|
||||||
|
b'a'..=b'f' => b - b'a' + 0xA,
|
||||||
|
b'A'..=b'F' => b - b'A' + 0xA,
|
||||||
|
_ => bail!("not a hexadecimal digit: {}", char::from(b)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse hexadecimal digits into a byte array.
|
||||||
|
pub fn hex_to_bin_exact(hex: &str, out: &mut [u8]) -> Result<(), Error> {
|
||||||
|
let bytes = hex.as_bytes();
|
||||||
|
|
||||||
|
if bytes.len() != out.len() * 2 {
|
||||||
|
bail!(
|
||||||
|
"hexadecimal string has invalid length ({}, expected {})",
|
||||||
|
bytes.len(),
|
||||||
|
out.len() * 2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..out.len() {
|
||||||
|
let h = hex_nibble_to_byte(bytes[i * 2])?;
|
||||||
|
let l = hex_nibble_to_byte(bytes[i * 2 + 1])?;
|
||||||
|
out[i] = (h << 4) | l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert a string of hexadecimal digits to a byte vector. Any non-digits are treated as an
|
/// Convert a string of hexadecimal digits to a byte vector. Any non-digits are treated as an
|
||||||
/// error, so when there is possible whitespace in the string it must be stripped by the caller
|
/// error, so when there is possible whitespace in the string it must be stripped by the caller
|
||||||
/// first. Also, only full bytes are allowed, so the input must consist of an even number of
|
/// first. Also, only full bytes are allowed, so the input must consist of an even number of
|
||||||
@ -151,78 +182,36 @@ pub fn bin_to_hex(digest: &[u8]) -> String {
|
|||||||
/// assert_eq!(&data, &[0xaa, 0xbb, 0x01, 0x23]);
|
/// assert_eq!(&data, &[0xaa, 0xbb, 0x01, 0x23]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn hex_to_bin(hex: &str) -> Result<Vec<u8>, Error> {
|
pub fn hex_to_bin(hex: &str) -> Result<Vec<u8>, Error> {
|
||||||
let mut result = vec![];
|
if (hex.len() % 2) != 0 {
|
||||||
|
|
||||||
let bytes = hex.as_bytes();
|
|
||||||
|
|
||||||
if (bytes.len() % 2) != 0 {
|
|
||||||
bail!("hex_to_bin: got wrong input length.");
|
bail!("hex_to_bin: got wrong input length.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = |c| {
|
let mut out = unsafe { vec::uninitialized(hex.len() / 2) };
|
||||||
if c >= b'0' && c <= b'9' {
|
hex_to_bin_exact(hex, &mut out)?;
|
||||||
return Ok(c - b'0');
|
Ok(out)
|
||||||
}
|
|
||||||
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.");
|
|
||||||
};
|
|
||||||
|
|
||||||
for pair in bytes.chunks(2) {
|
|
||||||
let h = val(pair[0])?;
|
|
||||||
let l = val(pair[1])?;
|
|
||||||
result.push((h << 4) | l);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This should be renamed to contain the digest algorithm, so that the array's size makes
|
// FIXME: This should be renamed to contain the digest algorithm, so that the array's size makes
|
||||||
// sense.
|
// sense.
|
||||||
pub fn hex_to_digest(hex: &str) -> Result<[u8; 32], Error> {
|
pub fn hex_to_digest(hex: &str) -> Result<[u8; 32], Error> {
|
||||||
let mut digest = [0u8; 32];
|
let mut digest = [0u8; 32];
|
||||||
|
hex_to_bin_exact(hex, &mut digest)?;
|
||||||
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)
|
Ok(digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hex() {
|
||||||
|
let mut out = [0u8; 5];
|
||||||
|
hex_to_bin_exact("abCA01239f", &mut out).expect("failed to parse hex digit");
|
||||||
|
assert_eq!(out, *b"\xab\xca\x01\x23\x9f");
|
||||||
|
let v = hex_to_bin("abCA01239f").expect("failed to parse hex digit");
|
||||||
|
assert_eq!(v, out);
|
||||||
|
|
||||||
|
hex_to_bin_exact("abca01239", &mut out).expect_err("parsed invalid hex string");
|
||||||
|
hex_to_bin_exact("abca01239fa", &mut out).expect_err("parsed invalid hex string");
|
||||||
|
hex_to_bin_exact("abca0x239f", &mut out).expect_err("parsed invalid hex string");
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the hosts node name (UTS node name)
|
/// Returns the hosts node name (UTS node name)
|
||||||
pub fn nodename() -> &'static str {
|
pub fn nodename() -> &'static str {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
Loading…
Reference in New Issue
Block a user