use std::sync::Mutex;
use mkit_attest::{RepoKeySigner, Signer as AttestSigner};
use mkit_core::hash::to_hex_bytes;
use mkit_core::sign::KeyPair;
use mkit_keystore::{KeyRef, KeySelector, KeySigner, open_backend};
use mkit_transport_connect::EnvelopeSigner;
use crate::config::Config;
pub(crate) struct RepoKeyEnvelopeSigner {
public_key_hex: String,
inner: Mutex<RepoKeySigner>,
}
impl RepoKeyEnvelopeSigner {
pub(crate) fn new(kp: KeyPair) -> Self {
let public_key_hex = to_hex_bytes(&kp.public.0);
Self {
public_key_hex,
inner: Mutex::new(RepoKeySigner::new(kp)),
}
}
}
impl EnvelopeSigner for RepoKeyEnvelopeSigner {
fn public_key_hex(&self) -> String {
self.public_key_hex.clone()
}
fn sign_hex(&self, message: &[u8; 32]) -> Result<String, String> {
let mut guard = self
.inner
.lock()
.map_err(|_| "repo-key signer mutex poisoned".to_owned())?;
let sig = guard.sign(message).map_err(|e| e.to_string())?;
Ok(to_hex_bytes(&sig))
}
}
pub(crate) struct KeystoreEnvelopeSigner {
public_key_hex: String,
signer: Mutex<Box<dyn KeySigner>>,
}
impl KeystoreEnvelopeSigner {
pub(crate) fn open(cfg: &Config) -> Result<Self, String> {
let key_ref = cfg
.key
.ed25519_ref_or_fallback()
.parse::<KeyRef>()
.map_err(|e| format!("key.ed25519_ref: {e}"))?;
let store =
open_backend(key_ref.backend()).map_err(|e| format!("keystore backend: {e}"))?;
let selector = KeySelector::new(
key_ref.label().to_owned(),
Some(mkit_keystore::Algorithm::Ed25519),
)
.map_err(|e| format!("key.ed25519_ref: {e}"))?;
let opener = store.opener().ok_or_else(|| {
format!(
"keystore backend `{}` does not support opening keys",
key_ref.backend()
)
})?;
let signer = opener.open(&selector).map_err(|e| match e {
mkit_keystore::Error::KeyNotFound(_) => format!(
"missing keystore signing key for algorithm ed25519 — run `mkit key generate --backend {} --algorithm ed25519 --label <label>` first: {e}",
key_ref.backend()
),
other => format!("keystore signing key for algorithm ed25519: {other}"),
})?;
let public = signer
.public_key()
.map_err(|e| format!("keystore public key: {e}"))?;
if public.as_bytes().len() != 32 {
return Err(format!(
"keystore Ed25519 public key must be 32 bytes, got {}",
public.as_bytes().len()
));
}
Ok(Self {
public_key_hex: to_hex_bytes(public.as_bytes()),
signer: Mutex::new(signer),
})
}
}
impl EnvelopeSigner for KeystoreEnvelopeSigner {
fn public_key_hex(&self) -> String {
self.public_key_hex.clone()
}
fn sign_hex(&self, message: &[u8; 32]) -> Result<String, String> {
let mut guard = self
.signer
.lock()
.map_err(|_| "keystore signer mutex poisoned".to_owned())?;
let sig = guard.sign(message).map_err(|e| e.to_string())?;
if sig.len() != 64 {
return Err(format!(
"keystore Ed25519 signature must be 64 bytes, got {}",
sig.len()
));
}
Ok(to_hex_bytes(&sig))
}
}