use serde::{Deserialize, Serialize};
use zeroize::ZeroizeOnDrop;
use crate::error::PlatformError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum KeyType {
Ed25519,
X25519,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct KeyHandle(u64);
impl KeyHandle {
#[must_use]
pub const fn new(id: u64) -> Self {
Self(id)
}
#[must_use]
pub const fn id(&self) -> u64 {
self.0
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct PublicKey(Vec<u8>);
impl PublicKey {
#[must_use]
pub const fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Signature(Vec<u8>);
impl Signature {
#[must_use]
pub const fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
}
#[derive(Debug, PartialEq, Eq, ZeroizeOnDrop)]
pub struct SharedSecret([u8; 32]);
impl SharedSecret {
#[must_use]
pub const fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
#[must_use]
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
#[derive(Debug, Clone)]
pub struct PseudonymKeypair {
pub public_key: PublicKey,
pub key_handle: KeyHandle,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CustodyType {
InMemory,
Hardware,
Software,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DeviceAttestationToken(Vec<u8>);
impl DeviceAttestationToken {
#[must_use]
pub const fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PushToken(Vec<u8>);
impl PushToken {
#[must_use]
pub const fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WakeSignal {
pub payload: Vec<u8>,
}
impl WakeSignal {
#[must_use]
pub const fn new(payload: Vec<u8>) -> Self {
Self { payload }
}
}
pub trait KeyCustody: Send + Sync {
fn generate_keypair(
&self,
key_type: KeyType,
) -> impl Future<Output = Result<KeyHandle, PlatformError>> + Send;
fn sign(
&self,
key: &KeyHandle,
data: &[u8],
) -> impl Future<Output = Result<Signature, PlatformError>> + Send;
fn public_key(
&self,
key: &KeyHandle,
) -> impl Future<Output = Result<PublicKey, PlatformError>> + Send;
fn destroy_key(
&self,
key: &KeyHandle,
) -> impl Future<Output = Result<(), PlatformError>> + Send;
fn dh_agree(
&self,
key: &KeyHandle,
peer_public: &[u8; 32],
) -> impl Future<Output = Result<SharedSecret, PlatformError>> + Send;
fn derive_pseudonym(
&self,
key: &KeyHandle,
context_id: &[u8],
) -> impl Future<Output = Result<PseudonymKeypair, PlatformError>> + Send;
fn derive_rotatable_pseudonym(
&self,
key: &KeyHandle,
context_id: &[u8],
pseudonym_epoch: u64,
) -> impl Future<Output = Result<PseudonymKeypair, PlatformError>> + Send;
fn custody_type(&self, key: &KeyHandle) -> CustodyType;
}
pub trait DeviceAttestation: Send + Sync {
fn attest(&self) -> impl Future<Output = Result<DeviceAttestationToken, PlatformError>> + Send;
fn verify(
&self,
token: &DeviceAttestationToken,
) -> impl Future<Output = Result<bool, PlatformError>> + Send;
}
pub trait Push: Send + Sync {
fn register(&self) -> impl Future<Output = Result<PushToken, PlatformError>> + Send;
fn handle_notification(
&self,
payload: &[u8],
) -> impl Future<Output = Result<WakeSignal, PlatformError>> + Send;
}
pub trait Storage: Send + Sync {
fn store(
&self,
key: &str,
data: &[u8],
) -> impl Future<Output = Result<(), PlatformError>> + Send;
fn retrieve(
&self,
key: &str,
) -> impl Future<Output = Result<Option<Vec<u8>>, PlatformError>> + Send;
fn delete(&self, key: &str) -> impl Future<Output = Result<(), PlatformError>> + Send;
fn list_keys(
&self,
prefix: &str,
) -> impl Future<Output = Result<Vec<String>, PlatformError>> + Send;
fn delete_prefix(
&self,
prefix: &str,
) -> impl Future<Output = Result<u64, PlatformError>> + Send;
fn exists(&self, key: &str) -> impl Future<Output = Result<bool, PlatformError>> + Send;
}
#[allow(clippy::manual_async_fn)]
impl<T: Storage> Storage for std::sync::Arc<T> {
fn store(
&self,
key: &str,
data: &[u8],
) -> impl Future<Output = Result<(), PlatformError>> + Send {
(**self).store(key, data)
}
fn retrieve(
&self,
key: &str,
) -> impl Future<Output = Result<Option<Vec<u8>>, PlatformError>> + Send {
(**self).retrieve(key)
}
fn delete(&self, key: &str) -> impl Future<Output = Result<(), PlatformError>> + Send {
(**self).delete(key)
}
fn list_keys(
&self,
prefix: &str,
) -> impl Future<Output = Result<Vec<String>, PlatformError>> + Send {
(**self).list_keys(prefix)
}
fn delete_prefix(
&self,
prefix: &str,
) -> impl Future<Output = Result<u64, PlatformError>> + Send {
(**self).delete_prefix(prefix)
}
fn exists(&self, key: &str) -> impl Future<Output = Result<bool, PlatformError>> + Send {
(**self).exists(key)
}
}