1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum SignatureAlgorithm {
9 EcdsaP256Sha256,
10}
11
12#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
17pub enum DelegationAudience {
18 Roles(Vec<CanisterRole>),
19 Principals(Vec<Principal>),
20 RolesOrPrincipals {
21 roles: Vec<CanisterRole>,
22 principals: Vec<Principal>,
23 },
24}
25
26#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
31pub struct RootPublicKey {
32 pub root_pid: Principal,
33 pub key_id: String,
34 pub alg: SignatureAlgorithm,
35 pub public_key_sec1: Vec<u8>,
36 pub key_hash: [u8; 32],
37 pub not_before: u64,
38 pub not_after: Option<u64>,
39}
40
41#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
46pub struct RootTrustAnchor {
47 pub root_pid: Principal,
48 pub root_key: RootPublicKey,
49}
50
51#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
56pub enum ShardKeyBinding {
57 IcThresholdEcdsa {
58 key_name_hash: [u8; 32],
59 derivation_path_hash: [u8; 32],
60 },
61}
62
63#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
68pub struct DelegationCert {
69 pub version: u16,
70 pub root_pid: Principal,
71 pub root_key_id: String,
72 pub root_key_hash: [u8; 32],
73 pub alg: SignatureAlgorithm,
74 pub shard_pid: Principal,
75 pub shard_key_id: String,
76 pub shard_public_key_sec1: Vec<u8>,
77 pub shard_key_hash: [u8; 32],
78 pub shard_key_binding: ShardKeyBinding,
79 pub issued_at: u64,
80 pub expires_at: u64,
81 pub max_token_ttl_secs: u64,
82 pub scopes: Vec<String>,
83 pub aud: DelegationAudience,
84 pub verifier_role_hash: Option<[u8; 32]>,
85}
86
87#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
92pub struct DelegationProof {
93 pub cert: DelegationCert,
94 pub root_sig: Vec<u8>,
95}
96
97#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
102pub struct DelegatedTokenClaims {
103 pub version: u16,
104 pub subject: Principal,
105 pub issuer_shard_pid: Principal,
106 pub cert_hash: [u8; 32],
107 pub issued_at: u64,
108 pub expires_at: u64,
109 pub aud: DelegationAudience,
110 pub scopes: Vec<String>,
111 pub nonce: [u8; 16],
112}
113
114#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct DelegatedToken {
120 pub claims: DelegatedTokenClaims,
121 pub proof: DelegationProof,
122 pub shard_sig: Vec<u8>,
123}
124
125#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
130pub struct DelegationProofIssueRequest {
131 pub shard_pid: Principal,
132 pub scopes: Vec<String>,
133 pub aud: DelegationAudience,
134 pub cert_ttl_secs: u64,
135}
136
137#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
142pub struct DelegatedTokenIssueRequest {
143 pub proof: DelegationProof,
144 pub subject: Principal,
145 pub aud: DelegationAudience,
146 pub scopes: Vec<String>,
147 pub ttl_secs: u64,
148 pub nonce: [u8; 16],
149}
150
151#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
156pub struct DelegatedTokenMintRequest {
157 pub subject: Principal,
158 pub aud: DelegationAudience,
159 pub scopes: Vec<String>,
160 pub token_ttl_secs: u64,
161 pub cert_ttl_secs: u64,
162 pub nonce: [u8; 16],
163}
164
165#[derive(CandidType, Clone, Debug, Deserialize)]
170pub struct RoleAttestationRequest {
171 pub subject: Principal,
172 pub role: CanisterRole,
173 #[serde(default)]
174 pub subnet_id: Option<Principal>,
175 pub audience: Principal,
176 pub ttl_secs: u64,
177 pub epoch: u64,
178 #[serde(default)]
179 pub metadata: Option<RootRequestMetadata>,
180}
181
182#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
187pub struct RoleAttestation {
188 pub subject: Principal,
189 pub role: CanisterRole,
190 #[serde(default)]
191 pub subnet_id: Option<Principal>,
192 pub audience: Principal,
193 pub issued_at: u64,
194 pub expires_at: u64,
195 pub epoch: u64,
196}
197
198#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
203pub struct SignedRoleAttestation {
204 pub payload: RoleAttestation,
205 pub signature: Vec<u8>,
206 pub key_id: u32,
207}
208
209#[derive(CandidType, Clone, Debug, Deserialize)]
214pub struct InternalInvocationProofRequest {
215 pub subject: Principal,
216 pub role: CanisterRole,
217 #[serde(default)]
218 pub subnet_id: Option<Principal>,
219 pub audience: Principal,
220 pub audience_method: String,
221 pub ttl_secs: u64,
222 #[serde(default)]
223 pub metadata: Option<RootRequestMetadata>,
224}
225
226#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
231pub struct InternalInvocationProofPayloadV1 {
232 pub subject: Principal,
233 pub role: CanisterRole,
234 #[serde(default)]
235 pub subnet_id: Option<Principal>,
236 pub audience: Principal,
237 pub audience_method: String,
238 pub issued_at: u64,
239 pub expires_at: u64,
240 pub epoch: u64,
241}
242
243#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
248pub struct SignedInternalInvocationProofV1 {
249 pub payload: InternalInvocationProofPayloadV1,
250 pub signature: Vec<u8>,
251 pub key_id: u32,
252}
253
254#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
259pub struct CanicInternalCallHeaderV1 {
260 pub target_canister: Principal,
261 pub target_method: String,
262}
263
264#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
269pub struct CanicInternalCallEnvelopeV1 {
270 pub version: u16,
271 pub header: CanicInternalCallHeaderV1,
272 pub proof: SignedInternalInvocationProofV1,
273 pub args: Vec<u8>,
274}
275
276#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
281pub enum AttestationKeyStatus {
282 Current,
283 Previous,
284}
285
286#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
291pub struct AttestationKey {
292 pub key_id: u32,
293 pub public_key: Vec<u8>,
294 pub key_name: String,
295 pub key_hash: [u8; 32],
296 pub status: AttestationKeyStatus,
297 #[serde(default)]
298 pub valid_from: Option<u64>,
299 #[serde(default)]
300 pub valid_until: Option<u64>,
301}
302
303#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
308pub struct AttestationKeySet {
309 pub root_pid: Principal,
310 pub generated_at: u64,
311 pub keys: Vec<AttestationKey>,
312}
313
314#[cfg(test)]
315mod tests {
316 #[test]
317 fn auth_dtos_remain_passive_boundary_types() {
318 let source = include_str!("auth.rs");
319 let production_source = source
320 .split("#[cfg(test)]")
321 .next()
322 .expect("production source exists");
323
324 for marker in [
325 "impl DelegatedToken",
326 "impl DelegatedTokenClaims",
327 "impl RoleAttestation",
328 "impl SignedRoleAttestation",
329 "impl InternalInvocationProofPayloadV1",
330 "impl SignedInternalInvocationProofV1",
331 "impl CanicInternalCallEnvelopeV1",
332 "fn verify",
333 "fn sign",
334 "fn resolve",
335 "fn replay",
336 "fn consume",
337 "fn policy",
338 "fn validate",
339 ] {
340 assert!(
341 !production_source.contains(marker),
342 "auth DTOs must stay passive; found marker `{marker}`"
343 );
344 }
345 }
346}