I've tried as best I can, to implement HMAC as specified in the RFC 2104. This is also my first Rust project, so the chances that rookie mistakes have been made are high. Since I'm fairly new to the language, I'm looking for feedback in general.
use functions;
use ring::{digest, test};
// Set blocksizes
pub const BLOCKSIZE_256: usize = 64;
pub const BLOCKSIZE_512: usize = 128;
/// Return either a SHA256 or SHA512 digest of byte vector
fn hash(variant: i32, mut data: Vec<u8>) -> Vec<u8> {
if variant == 256 {
data = (digest::digest(&digest::SHA256, &data).as_ref()).to_vec();
} else if variant == 512 {
data = (digest::digest(&digest::SHA512, &data).as_ref()).to_vec();
} else {
panic!("Invalid variant. Valid variants are 256 and 512.");
}
return data;
}
/// Return a key k that has been padded to fit the selected blocksize
fn key_deriv(variant: i32, mut k: Vec<u8>) -> Vec<u8> {
if variant == 256 {
// If key k is bigger than blocksize, it should be hashed and then padded with zeroes
// to fit blocksize
if k.len() > BLOCKSIZE_256 {
k = hash(variant, k);
}
while k.len() < BLOCKSIZE_256 {
k.push(0x00);
}
return k;
} else if variant == 512 {
if k.len() > BLOCKSIZE_512 {
k = hash(variant, k);
}
while k.len() < BLOCKSIZE_512 {
k.push(0x00);
}
return k;
} else {
panic!("Invalid variant. Valid variants are 256 and 512.");
}
}
/// Returns an HMAC from message m and key k
pub fn hmac(variant: i32, mut k: Vec<u8>, mut m: Vec<u8>) -> Vec<u8> {
// Initialize vectors that will hold the ipad and opad
let mut ipad = vec![];
let mut opad = vec![];
// Pad the key
k = key_deriv(variant, k);
for count in 0..k.len() {
ipad.push(k[count] ^ 0x36);
opad.push(k[count] ^ 0x5C);
}
ipad.append(&mut m);
ipad = hash(variant, ipad);
opad.append(&mut ipad);
opad = hash(variant, opad);
return opad;
}
A possible improvement I'm considering is to change the zero padding of k in key_deriv()
. Right now it operates on a while loop, but I noticed that an approach like below, was slightly faster. Though I suspected it might be a little more memory intensive because of the vector allocation and I'm not sure which of the two to choose.
let len = k.len();
if len < BLOCKSIZE_256 {
k.append(&mut vec![0x00; (BLOCKSIZE_256-len)]);
}