use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD as BASE64;
use serde::{Deserialize, Serialize};
use super::error::SealedTransferError;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BootstrapRequest {
pub version: u8,
pub client_did: String,
pub nonce: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
impl BootstrapRequest {
pub fn new(client_ed25519_pub: [u8; 32], nonce: [u8; 16], label: Option<String>) -> Self {
Self {
version: 1,
client_did: affinidi_crypto::did_key::ed25519_pub_to_did_key(&client_ed25519_pub),
nonce: BASE64.encode(nonce),
label,
}
}
pub fn decode_client_ed25519_pub(&self) -> Result<[u8; 32], SealedTransferError> {
affinidi_crypto::did_key::did_key_to_ed25519_pub(&self.client_did)
.map_err(|e| SealedTransferError::Wire(format!("client_did: {e}")))
}
pub fn decode_client_x25519_pub(&self) -> Result<[u8; 32], SealedTransferError> {
let ed = self.decode_client_ed25519_pub()?;
affinidi_crypto::did_key::ed25519_pub_to_x25519_bytes(&ed)
.map_err(|e| SealedTransferError::Wire(format!("client_did X25519 derivation: {e}")))
}
pub fn decode_nonce(&self) -> Result<[u8; 16], SealedTransferError> {
let raw = BASE64
.decode(&self.nonce)
.map_err(|e| SealedTransferError::Base64(e.to_string()))?;
raw.try_into()
.map_err(|_| SealedTransferError::Wire("nonce must be 16 bytes".into()))
}
}