use anyhow::{anyhow, ensure, Context, Result};
use serde::{Deserialize, Serialize};
use serde_annotate::Annotate;
use std::io::{Read, Write};
use std::str::FromStr;
use super::Error;
use sphincsplus::{DecodeKey, SpxPublicKey};
#[derive(Debug, Serialize, Deserialize, Annotate)]
pub struct SpxRawPublicKey {
#[serde(with = "serde_bytes")]
#[annotate(format = hexstr)]
pub key: Vec<u8>,
}
impl Default for SpxRawPublicKey {
fn default() -> Self {
Self { key: vec![0; 32] }
}
}
impl TryFrom<&sphincsplus::SpxPublicKey> for SpxRawPublicKey {
type Error = Error;
fn try_from(v: &SpxPublicKey) -> Result<Self, Self::Error> {
Ok(Self {
key: v.as_bytes().to_vec(),
})
}
}
impl FromStr for SpxRawPublicKey {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let key = SpxPublicKey::read_pem_file(s)
.with_context(|| format!("Failed to load {s}"))
.map_err(Error::Other)?;
SpxRawPublicKey::try_from(&key)
}
}
impl SpxRawPublicKey {
pub const SIZE: usize = 32;
pub fn read(src: &mut impl Read) -> Result<Self> {
let mut key = Self::default();
key.key.resize(32, 0);
src.read_exact(&mut key.key)?;
Ok(key)
}
pub fn write(&self, dest: &mut impl Write) -> Result<()> {
ensure!(
self.key.len() == Self::SIZE,
Error::InvalidPublicKey(anyhow!("bad key length: {}", self.key.len()))
);
dest.write_all(&self.key)?;
Ok(())
}
}