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 Role(CanisterRole),
19 Principal(Principal),
20}
21
22#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
27pub struct RootPublicKey {
28 pub root_pid: Principal,
29 pub key_id: String,
30 pub alg: SignatureAlgorithm,
31 pub public_key_sec1: Vec<u8>,
32 pub key_hash: [u8; 32],
33 pub not_before: u64,
34 pub not_after: Option<u64>,
35}
36
37#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
42pub struct RootTrustAnchor {
43 pub root_pid: Principal,
44 pub root_key: RootPublicKey,
45}
46
47#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
52pub enum ShardKeyBinding {
53 IcThresholdEcdsa {
54 key_name_hash: [u8; 32],
55 derivation_path_hash: [u8; 32],
56 },
57}
58
59#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
64pub struct DelegationCert {
65 pub version: u16,
66 pub root_pid: Principal,
67 pub root_key_id: String,
68 pub root_key_hash: [u8; 32],
69 pub alg: SignatureAlgorithm,
70 pub shard_pid: Principal,
71 pub shard_key_id: String,
72 pub shard_public_key_sec1: Vec<u8>,
73 pub shard_key_hash: [u8; 32],
74 pub shard_key_binding: ShardKeyBinding,
75 pub issued_at: u64,
76 pub expires_at: u64,
77 pub max_token_ttl_secs: u64,
78 pub scopes: Vec<String>,
79 pub aud: DelegationAudience,
80 pub verifier_role_hash: Option<[u8; 32]>,
81}
82
83#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
88pub struct DelegationProof {
89 pub cert: DelegationCert,
90 pub root_sig: Vec<u8>,
91}
92
93#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
98pub struct DelegatedTokenClaims {
99 pub version: u16,
100 pub subject: Principal,
101 pub issuer_shard_pid: Principal,
102 pub cert_hash: [u8; 32],
103 pub issued_at: u64,
104 pub expires_at: u64,
105 pub aud: DelegationAudience,
106 pub scopes: Vec<String>,
107 pub nonce: [u8; 16],
108}
109
110#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
115pub struct DelegatedToken {
116 pub claims: DelegatedTokenClaims,
117 pub proof: DelegationProof,
118 pub shard_sig: Vec<u8>,
119}
120
121#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
126pub struct DelegationProofIssueRequest {
127 #[serde(default)]
128 pub metadata: Option<RootRequestMetadata>,
129 pub shard_pid: Principal,
130 pub scopes: Vec<String>,
131 pub aud: DelegationAudience,
132 pub cert_ttl_secs: u64,
133}
134
135#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
140pub struct DelegatedTokenIssueRequest {
141 pub proof: DelegationProof,
142 pub subject: Principal,
143 pub aud: DelegationAudience,
144 pub scopes: Vec<String>,
145 pub ttl_secs: u64,
146 pub nonce: [u8; 16],
147}
148
149#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
154pub struct DelegatedTokenMintRequest {
155 pub subject: Principal,
156 pub aud: DelegationAudience,
157 pub scopes: Vec<String>,
158 pub token_ttl_secs: u64,
159 pub cert_ttl_secs: u64,
160 pub nonce: [u8; 16],
161}
162
163#[derive(CandidType, Clone, Debug, Deserialize)]
168pub struct RoleAttestationRequest {
169 pub subject: Principal,
170 pub role: CanisterRole,
171 #[serde(default)]
172 pub subnet_id: Option<Principal>,
173 pub audience: Principal,
174 pub ttl_secs: u64,
175 pub epoch: u64,
176 #[serde(default)]
177 pub metadata: Option<RootRequestMetadata>,
178}
179
180#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
185pub struct RoleAttestation {
186 pub subject: Principal,
187 pub role: CanisterRole,
188 #[serde(default)]
189 pub subnet_id: Option<Principal>,
190 pub audience: Principal,
191 pub issued_at: u64,
192 pub expires_at: u64,
193 pub epoch: u64,
194}
195
196#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
201pub struct SignedRoleAttestation {
202 pub payload: RoleAttestation,
203 pub signature: Vec<u8>,
204 pub key_id: u32,
205}
206
207#[derive(CandidType, Clone, Debug, Deserialize)]
212pub struct InternalInvocationProofRequest {
213 pub subject: Principal,
214 pub role: CanisterRole,
215 #[serde(default)]
216 pub subnet_id: Option<Principal>,
217 pub audience: Principal,
218 pub audience_method: String,
219 pub ttl_secs: u64,
220 #[serde(default)]
221 pub metadata: Option<RootRequestMetadata>,
222}
223
224#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
229pub struct InternalInvocationProofPayloadV1 {
230 pub subject: Principal,
231 pub role: CanisterRole,
232 #[serde(default)]
233 pub subnet_id: Option<Principal>,
234 pub audience: Principal,
235 pub audience_method: String,
236 pub issued_at: u64,
237 pub expires_at: u64,
238 pub epoch: u64,
239}
240
241#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
246pub struct SignedInternalInvocationProofV1 {
247 pub payload: InternalInvocationProofPayloadV1,
248 pub signature: Vec<u8>,
249 pub key_id: u32,
250}
251
252#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
257pub struct CanicInternalCallHeaderV1 {
258 pub target_canister: Principal,
259 pub target_method: String,
260}
261
262#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
267pub struct CanicInternalCallEnvelopeV1 {
268 pub version: u16,
269 pub header: CanicInternalCallHeaderV1,
270 pub proof: SignedInternalInvocationProofV1,
271 pub args: Vec<u8>,
272}
273
274#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
279pub enum AttestationKeyStatus {
280 Current,
281 Previous,
282}
283
284#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
289pub struct AttestationKey {
290 pub key_id: u32,
291 pub public_key: Vec<u8>,
292 pub key_name: String,
293 pub key_hash: [u8; 32],
294 pub status: AttestationKeyStatus,
295 #[serde(default)]
296 pub valid_from: Option<u64>,
297 #[serde(default)]
298 pub valid_until: Option<u64>,
299}
300
301#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
306pub struct AttestationKeySet {
307 pub root_pid: Principal,
308 pub generated_at: u64,
309 pub keys: Vec<AttestationKey>,
310}
311
312#[cfg(test)]
313mod tests {
314 #[test]
315 fn auth_dtos_remain_passive_boundary_types() {
316 let source = include_str!("auth.rs");
317 let production_source = source
318 .split("#[cfg(test)]")
319 .next()
320 .expect("production source exists");
321
322 for marker in [
323 "impl DelegatedToken",
324 "impl DelegatedTokenClaims",
325 "impl RoleAttestation",
326 "impl SignedRoleAttestation",
327 "impl InternalInvocationProofPayloadV1",
328 "impl SignedInternalInvocationProofV1",
329 "impl CanicInternalCallEnvelopeV1",
330 "fn verify",
331 "fn sign",
332 "fn resolve",
333 "fn replay",
334 "fn consume",
335 "fn policy",
336 "fn validate",
337 ] {
338 assert!(
339 !production_source.contains(marker),
340 "auth DTOs must stay passive; found marker `{marker}`"
341 );
342 }
343 }
344}