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}