Skip to main content

crypto_signer/
dispatch_signer.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crypto_core::Algorithm;
6use secrecy::{ExposeSecret, SecretBox};
7use zeroize::Zeroizing;
8
9use crate::{Signer, SignerError, SignerFailureKind};
10
11/// Local private-key signer implemented through `crypto_dispatch::sign`.
12///
13/// This adapter is useful for tests and native development. Production custody
14/// should prefer a platform keystore, HSM, QSCD, or remote signing adapter.
15#[derive(Debug)]
16pub struct DispatchSigner {
17    alg: Algorithm,
18    private_key: SecretBox<Zeroizing<Vec<u8>>>,
19}
20
21impl DispatchSigner {
22    /// Create a dispatch-backed signer from owned private-key material.
23    ///
24    /// Accepts either `Vec<u8>` or `Zeroizing<Vec<u8>>`; the key is stored in
25    /// a zeroizing secret wrapper either way.
26    pub fn new(alg: Algorithm, private_key: impl Into<Zeroizing<Vec<u8>>>) -> Self {
27        Self {
28            alg,
29            private_key: SecretBox::new(Box::new(private_key.into())),
30        }
31    }
32}
33
34impl Signer for DispatchSigner {
35    fn alg(&self) -> Algorithm {
36        self.alg
37    }
38
39    fn sign(&self, message: &[u8]) -> Result<Vec<u8>, SignerError> {
40        crypto_dispatch::sign(
41            self.alg,
42            self.private_key.expose_secret().as_slice(),
43            message,
44        )
45        .map_err(|source| SignerError::SignFailed {
46            algorithm: self.alg,
47            kind: SignerFailureKind::DispatchRejected,
48            source,
49        })
50    }
51}