Skip to main content

vta_sdk/protocols/key_management/
sign.rs

1use serde::{Deserialize, Serialize};
2
3/// Signing algorithms supported by the VTA sign-request protocol.
4/// Signing algorithms, spelled as the IANA JOSE registry spells them โ€”
5/// which is what the canonical `keys/_shared/0.1/sign-algorithm` enumeration
6/// publishes. The pre-fold lowercase forms are accepted on intake so a producer
7/// written against them keeps working while it migrates.
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
10pub enum SignAlgorithm {
11    /// Ed25519 / EdDSA signing.
12    #[serde(rename = "EdDSA", alias = "eddsa")]
13    EdDSA,
14    /// ECDSA with P-256 / ES256 signing.
15    #[serde(rename = "ES256", alias = "es256")]
16    ES256,
17}
18
19/// Body of a sign-request message.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
22pub struct SignRequestBody {
23    /// Key ID to sign with. Must be **active**, and the consumer enforces the
24    /// caller's authority over it โ€” this is not merely a caller-side
25    /// precondition.
26    ///
27    /// Because the VTA signs the bytes it is given without inspecting them,
28    /// *which keys a caller may name* is the whole of the authorization story,
29    /// so callers reasoning about identity separation depend on it. The
30    /// guarantee, in order: the caller must be authorized in the key's context;
31    /// the context's `signable_keys` policy must permit the key (binding even a
32    /// super-admin); and a key with no context is super-admin-only.
33    ///
34    /// **Scoped per context, not per key id** โ€” holding a context authorizes
35    /// every key in it, so a signer acting for several identities needs a
36    /// context each. See `docs/02-vta/integration-guide.md` ยง"What authorizes a
37    /// sign request".
38    #[serde(rename = "keyId", alias = "key_id")]
39    pub key_id: String,
40    /// Base64url-encoded payload bytes to sign.
41    pub payload: String,
42    /// Signing algorithm to use (must match the key type).
43    pub algorithm: SignAlgorithm,
44}
45
46/// Body of a sign-result message.
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
49pub struct SignResultBody {
50    /// Key ID that was used.
51    #[serde(rename = "keyId", alias = "key_id")]
52    pub key_id: String,
53    /// Base64url-encoded signature bytes.
54    pub signature: String,
55    /// Algorithm used.
56    pub algorithm: SignAlgorithm,
57}
58
59impl std::fmt::Display for SignAlgorithm {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        match self {
62            SignAlgorithm::EdDSA => write!(f, "eddsa"),
63            SignAlgorithm::ES256 => write!(f, "es256"),
64        }
65    }
66}