use crate::error::*;
use crate::signature::sig_sections::{SIGNATURE_SECTION_HEADER_NAME, SignatureData};
use crate::wasm_module::{Module, Section};
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::Path;
#[derive(Debug, Clone)]
pub struct SignatureInfo {
key_ids: Vec<Vec<u8>>,
signature_count: usize,
pub specification_version: u8,
pub content_type: u8,
pub hash_function: u8,
}
impl SignatureInfo {
fn from_signature_data(data: &SignatureData) -> Self {
let mut key_ids = Vec::new();
let mut signature_count = 0;
for signed_hashes in &data.signed_hashes_set {
for sig in &signed_hashes.signatures {
if let Some(key_id) = &sig.key_id {
key_ids.push(key_id.clone());
}
signature_count += 1;
}
}
SignatureInfo {
key_ids,
signature_count,
specification_version: data.specification_version,
content_type: data.content_type,
hash_function: data.hash_function,
}
}
pub fn key_ids(&self) -> &[Vec<u8>] {
&self.key_ids
}
pub fn signature_count(&self) -> usize {
self.signature_count
}
pub fn is_signed(&self) -> bool {
self.signature_count > 0
}
}
impl Module {
pub fn signature_info(&self) -> Result<SignatureInfo, WSError> {
for section in &self.sections {
if let Section::Custom(custom) = section {
if custom.is_signature_header() {
let data = custom.signature_data()?;
return Ok(SignatureInfo::from_signature_data(&data));
}
}
}
Err(WSError::NoSignatures)
}
}
pub fn signature_info_from_file(path: impl AsRef<Path>) -> Result<SignatureInfo, WSError> {
let fp = File::open(path.as_ref())?;
signature_info_from_reader(&mut BufReader::new(fp), None)
}
pub fn signature_info_from_reader(
reader: &mut impl Read,
detached_signature: Option<&[u8]>,
) -> Result<SignatureInfo, WSError> {
if let Some(detached) = detached_signature {
let data = SignatureData::deserialize(detached)?;
return Ok(SignatureInfo::from_signature_data(&data));
}
let stream = Module::init_from_reader(reader)?;
let mut sections = Module::iterate(stream)?;
let first_section = sections.next().ok_or(WSError::ParseError)??;
match first_section {
Section::Custom(custom) if custom.name() == SIGNATURE_SECTION_HEADER_NAME => {
let data = custom.signature_data()?;
Ok(SignatureInfo::from_signature_data(&data))
}
_ => Err(WSError::NoSignatures),
}
}
pub fn signature_info_from_detached(detached_signature: &[u8]) -> Result<SignatureInfo, WSError> {
let data = SignatureData::deserialize(detached_signature)?;
Ok(SignatureInfo::from_signature_data(&data))
}