use std::fs::File;
use std::io::{Read, Write};
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
use cfg_if::cfg_if;
use classic_mceliece_rust::PublicKey as McEliecePublicKey;
use ed25519_dalek::VerifyingKey;
cfg_if! {
if #[cfg(any(feature = "full_software", feature = "full_hardware"))] {
use x25519_dalek::PublicKey as X25519PublicKey;
use super::utils::X25519_BYTES;
}
}
use super::utils::{CertificateError, ED25519_BYTES, EPK_BYTES, ObfuscationBufferContainer, TYPE_CLIENT, read_addresses, read_header, write_addresses, write_header};
use crate::bytes::FixedByteBuffer;
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
#[derive(Clone, Debug)]
pub struct ClientCertificate {
pub(crate) epk: Arc<McEliecePublicKey<'static>>,
pub(crate) vpk: VerifyingKey,
pub(crate) obfs: FixedByteBuffer<ED25519_BYTES>,
pub(crate) addresses: Vec<SocketAddr>,
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
#[derive(Clone, Debug)]
pub struct ClientCertificate {
pub(crate) epk: Arc<McEliecePublicKey<'static>>,
pub(crate) vpk: VerifyingKey,
pub(crate) opk: X25519PublicKey,
pub(crate) addresses: Vec<SocketAddr>,
}
impl ClientCertificate {
pub fn addresses(&self) -> &[SocketAddr] {
&self.addresses
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn save(&self, path: impl AsRef<Path>) -> Result<(), CertificateError> {
let mut f = File::create(path)?;
write_header(&mut f, TYPE_CLIENT)?;
f.write_all(self.epk.as_array())?;
f.write_all(&self.vpk.to_bytes())?;
f.write_all(self.obfs.as_ref())?;
write_addresses(&mut f, &self.addresses)?;
Ok(())
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn save(&self, path: impl AsRef<Path>) -> Result<(), CertificateError> {
let mut f = File::create(path)?;
write_header(&mut f, TYPE_CLIENT)?;
f.write_all(self.epk.as_array())?;
f.write_all(&self.vpk.to_bytes())?;
f.write_all(self.opk.as_bytes())?;
write_addresses(&mut f, &self.addresses)?;
Ok(())
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn load(path: impl AsRef<Path>) -> Result<Self, CertificateError> {
let mut f = File::open(path)?;
read_header(&mut f, TYPE_CLIENT)?;
let mut epk_buf = Box::new([0u8; EPK_BYTES]);
f.read_exact(epk_buf.as_mut())?;
let mut vpk_arr = [0u8; ED25519_BYTES];
f.read_exact(&mut vpk_arr)?;
let vpk = VerifyingKey::from_bytes(&vpk_arr).map_err(|_| CertificateError::InvalidKeyData)?;
let mut obfs_arr = [0u8; ED25519_BYTES];
f.read_exact(&mut obfs_arr)?;
let addresses = read_addresses(&mut f)?;
Ok(Self {
epk: Arc::new(McEliecePublicKey::from(epk_buf)),
vpk,
obfs: FixedByteBuffer::from(obfs_arr),
addresses,
})
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn load(path: impl AsRef<Path>) -> Result<Self, CertificateError> {
let mut f = File::open(path)?;
read_header(&mut f, TYPE_CLIENT)?;
let mut epk_buf = Box::new([0u8; EPK_BYTES]);
f.read_exact(epk_buf.as_mut())?;
let mut vpk_arr = [0u8; ED25519_BYTES];
f.read_exact(&mut vpk_arr)?;
let vpk = VerifyingKey::from_bytes(&vpk_arr).map_err(|_| CertificateError::InvalidKeyData)?;
let mut opk_arr = [0u8; X25519_BYTES];
f.read_exact(&mut opk_arr)?;
let addresses = read_addresses(&mut f)?;
Ok(Self {
epk: Arc::new(McEliecePublicKey::from(epk_buf)),
vpk,
opk: X25519PublicKey::from(opk_arr),
addresses,
})
}
}
impl ObfuscationBufferContainer for ClientCertificate {
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
#[inline]
fn obfuscation_buffer(&self) -> FixedByteBuffer<ED25519_BYTES> {
FixedByteBuffer::from(self.opk.as_bytes())
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
#[inline]
fn obfuscation_buffer(&self) -> FixedByteBuffer<ED25519_BYTES> {
self.obfs
}
}