use x509_parser::der_parser::{
der::{parse_der_integer, parse_der_sequence_defined_g},
error::BerResult,
};
use crate::raw_signature::{RawSignerError, SigningAlg};
pub fn parse_ec_der_sig(data: &[u8]) -> BerResult<EcSigComps> {
parse_der_sequence_defined_g(|content: &[u8], _| {
let (rem1, r) = parse_der_integer(content)?;
let (_rem2, s) = parse_der_integer(rem1)?;
Ok((
data,
EcSigComps {
r: r.as_slice()?,
s: s.as_slice()?,
},
))
})(data)
}
#[allow(missing_docs)]
pub struct EcSigComps<'a> {
pub r: &'a [u8],
pub s: &'a [u8],
}
pub(crate) fn der_to_p1363(data: &[u8], alg: SigningAlg) -> Result<Vec<u8>, RawSignerError> {
let (_, p) = parse_ec_der_sig(data)
.map_err(|err| RawSignerError::InternalError(format!("invalid DER signature: {err}")))?;
let mut r = const_hex::encode(p.r);
let mut s = const_hex::encode(p.s);
let sig_len: usize = match alg {
SigningAlg::Es256 => 64,
SigningAlg::Es384 => 96,
SigningAlg::Es512 => 132,
_ => {
return Err(RawSignerError::InternalError(
"unsupported algorithm for der_to_p1363".to_string(),
))
}
};
let rp = if r.len() > sig_len {
let offset = r.len() - sig_len;
&r[offset..r.len()]
} else {
while r.len() != sig_len {
r.insert(0, '0');
}
r.as_ref()
};
let sp = if s.len() > sig_len {
let offset = s.len() - sig_len;
&s[offset..s.len()]
} else {
while s.len() != sig_len {
s.insert(0, '0');
}
s.as_ref()
};
if rp.len() != sig_len || rp.len() != sp.len() {
return Err(RawSignerError::InternalError(
"invalid signature components".to_string(),
));
}
let new_sig = format!("{rp}{sp}");
const_hex::decode(&new_sig)
.map_err(|e| RawSignerError::InternalError(format!("invalid signature components {e}")))
}