62 lines
1.8 KiB
Rust
62 lines
1.8 KiB
Rust
//! Pure signing and public-key export over decrypted field values. No storage or grant policy.
|
|
use super::keys;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct Error {
|
|
pub kind: &'static str,
|
|
pub message: &'static str,
|
|
}
|
|
impl std::fmt::Display for Error {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_str(self.message)
|
|
}
|
|
}
|
|
impl std::error::Error for Error {}
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
pub(super) fn error(kind: &'static str, message: &'static str) -> Error {
|
|
Error { kind, message }
|
|
}
|
|
pub(super) fn invalid_key() -> Error {
|
|
error("invalid_key", "invalid signing key encoding or length")
|
|
}
|
|
|
|
#[derive(Debug, serde::Serialize)]
|
|
pub struct SignResult {
|
|
pub signature: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub bytes: Option<Vec<u8>>,
|
|
}
|
|
|
|
/// Sign bytes. RSA requires explicit, matching padding and digest parameters.
|
|
pub fn sign(
|
|
value: &str,
|
|
passphrase: Option<&str>,
|
|
format: &str,
|
|
payload: &[u8],
|
|
output: &str,
|
|
padding: Option<&str>,
|
|
hash: Option<&str>,
|
|
) -> Result<SignResult> {
|
|
keys::check(format, padding, hash)?;
|
|
let key = keys::read(value, format, passphrase)?;
|
|
keys::output(format, output, keys::sign_key(&key, format, payload)?)
|
|
}
|
|
|
|
/// Export only the public part of an asymmetric key.
|
|
pub fn public_key(
|
|
value: &str,
|
|
passphrase: Option<&str>,
|
|
format: &str,
|
|
output: &str,
|
|
) -> Result<String> {
|
|
keys::public(&keys::read(value, format, passphrase)?, output)
|
|
}
|
|
|
|
/// Generate a P-256 private key in PKCS#8 PEM format for ES256.
|
|
pub fn generate_es256() -> Result<zeroize::Zeroizing<String>> {
|
|
use p256::pkcs8::EncodePrivateKey;
|
|
p256::SecretKey::random(&mut rsa::rand_core::OsRng)
|
|
.to_pkcs8_pem(Default::default())
|
|
.map_err(|_| invalid_key())
|
|
}
|