opentitanlib/crypto/
spx.rs1use std::io::{Read, Write};
6use std::str::FromStr;
7
8use anyhow::{Context, Result, anyhow, ensure};
9use serde::Deserialize;
10use serde_annotate::Annotate;
11use sphincsplus::{DecodeKey, SpxPublicKey};
12
13use super::Error;
14
15#[derive(Debug, Deserialize, Annotate)]
16pub struct SpxRawPublicKey {
17 #[serde(with = "serde_bytes")]
18 #[annotate(format = hexstr)]
19 pub key: Vec<u8>,
20}
21
22impl Default for SpxRawPublicKey {
23 fn default() -> Self {
24 Self { key: vec![0; 32] }
25 }
26}
27
28impl TryFrom<&sphincsplus::SpxPublicKey> for SpxRawPublicKey {
29 type Error = Error;
30 fn try_from(v: &SpxPublicKey) -> Result<Self, Self::Error> {
31 Ok(Self {
32 key: v.as_bytes().to_vec(),
33 })
34 }
35}
36
37impl TryFrom<sphincsplus::SpxPublicKey> for SpxRawPublicKey {
38 type Error = Error;
39 fn try_from(v: SpxPublicKey) -> Result<Self, Self::Error> {
40 (&v).try_into()
41 }
42}
43
44impl FromStr for SpxRawPublicKey {
45 type Err = Error;
46 fn from_str(s: &str) -> Result<Self, Self::Err> {
47 let key = SpxPublicKey::read_pem_file(s)
48 .with_context(|| format!("Failed to load {s}"))
49 .map_err(Error::Other)?;
50 SpxRawPublicKey::try_from(&key)
51 }
52}
53
54impl SpxRawPublicKey {
55 pub const SIZE: usize = 32;
56 pub fn read(src: &mut impl Read) -> Result<Self> {
57 let mut key = Self::default();
58 key.key.resize(32, 0);
59 src.read_exact(&mut key.key)?;
60 Ok(key)
61 }
62 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
63 ensure!(
64 self.key.len() == Self::SIZE,
65 Error::InvalidPublicKey(anyhow!("bad key length: {}", self.key.len()))
66 );
67 dest.write_all(&self.key)?;
68 Ok(())
69 }
70}