const SEQUENCE: u8 = 0x30;
const INTEGER: u8 = 0x02;
const OCTET_STRING: u8 = 0x04;
fn element(input: &[u8], tag: u8) -> Option<(&[u8], &[u8])> {
let (&first, rest) = input.split_first()?;
if first != tag {
return None;
}
let (&len0, rest) = rest.split_first()?;
let (len, rest) = if len0 < 0x80 {
(len0 as usize, rest)
} else {
let count = (len0 & 0x7f) as usize;
if count == 0 || count > 4 || rest.len() < count || rest[0] == 0 {
return None;
}
let len = rest[..count]
.iter()
.fold(0usize, |n, &b| (n << 8) | b as usize);
if len < 0x80 {
return None;
}
(len, &rest[count..])
};
if rest.len() < len {
return None;
}
Some(rest.split_at(len))
}
pub(super) fn rsa_public_key_is_4096_f4(der: &[u8]) -> bool {
let Some((body, [])) = element(der, SEQUENCE) else {
return false;
};
let Some((modulus, rest)) = element(body, INTEGER) else {
return false;
};
let Some((exponent, [])) = element(rest, INTEGER) else {
return false;
};
modulus.len() == 513
&& modulus[0] == 0
&& modulus[1] & 0x80 != 0
&& exponent == [0x01, 0x00, 0x01]
}
pub(super) fn pkcs1_of_pkcs8(pkcs8: &[u8]) -> Option<Vec<u8>> {
let (body, rest) = element(pkcs8, SEQUENCE)?;
if !rest.is_empty() {
return None;
}
let (_version, rest) = element(body, INTEGER)?;
let (_algorithm, rest) = element(rest, SEQUENCE)?;
let (key, _attributes) = element(rest, OCTET_STRING)?;
Some(key.to_vec())
}