use std::error::Error;
pub fn construct_payload(
key: &[u8],
masked_key_length: usize,
cipher_block_length: usize,
random_seed: &[u8],
) -> Result<Vec<u8>, Box<dyn Error>> {
let key_len = key.len();
let padding_length = calculate_padding_length(key_len, masked_key_length, cipher_block_length)?;
let mut payload = Vec::with_capacity(key_len + 2 + padding_length);
payload.extend_from_slice(&(8 * key_len as u16).to_be_bytes());
payload.extend_from_slice(key);
if random_seed.len() < padding_length {
return Err(
"ERROR TR-31 PAYLOAD: The provided random seed is too short for the padding requirement"
.into(),
);
}
payload.extend_from_slice(&random_seed[..padding_length]);
Ok(payload)
}
pub fn extract_key_from_payload(payload: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
if payload.len() < 2 {
return Err("ERROR TR-31 PAYLOAD: Payload too short to contain valid key length".into());
}
let key_length_bits = u16::from_be_bytes([payload[0], payload[1]]);
let key_length_bytes = (key_length_bits / 8) as usize;
if payload.len() < 2 + key_length_bytes {
return Err("ERROR TR-31 PAYLOAD: Payload too short for the specified key length".into());
}
let key = payload[2..2 + key_length_bytes].to_vec();
Ok(key)
}
pub fn calculate_padding_length(
key_len: usize,
masked_key_length: usize,
cipher_block_length: usize,
) -> Result<usize, Box<dyn Error>> {
let raw_key_section_length = 2 + key_len;
let effective_key_length = std::cmp::max(key_len, masked_key_length);
let total_payload_length = ((2 + effective_key_length + (cipher_block_length - 1))
/ cipher_block_length)
* cipher_block_length;
if total_payload_length < raw_key_section_length {
return Err("ERROR TR-31 PAYLOAD: Invalid total payload length".into());
}
let padding_length = total_payload_length - raw_key_section_length;
Ok(padding_length)
}