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 pub shard_pid: Principal,
128 pub scopes: Vec<String>,
129 pub aud: DelegationAudience,
130 pub cert_ttl_secs: u64,
131}
132
133#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
138pub struct DelegatedTokenIssueRequest {
139 pub proof: DelegationProof,
140 pub subject: Principal,
141 pub aud: DelegationAudience,
142 pub scopes: Vec<String>,
143 pub ttl_secs: u64,
144 pub nonce: [u8; 16],
145}
146
147#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
152pub struct DelegatedTokenMintRequest {
153 pub subject: Principal,
154 pub aud: DelegationAudience,
155 pub scopes: Vec<String>,
156 pub token_ttl_secs: u64,
157 pub cert_ttl_secs: u64,
158 pub nonce: [u8; 16],
159}
160
161#[derive(CandidType, Clone, Debug, Deserialize)]
166pub struct RoleAttestationRequest {
167 pub subject: Principal,
168 pub role: CanisterRole,
169 #[serde(default)]
170 pub subnet_id: Option<Principal>,
171 pub audience: Principal,
172 pub ttl_secs: u64,
173 pub epoch: u64,
174 #[serde(default)]
175 pub metadata: Option<RootRequestMetadata>,
176}
177
178#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
183pub struct RoleAttestation {
184 pub subject: Principal,
185 pub role: CanisterRole,
186 #[serde(default)]
187 pub subnet_id: Option<Principal>,
188 pub audience: Principal,
189 pub issued_at: u64,
190 pub expires_at: u64,
191 pub epoch: u64,
192}
193
194#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
199pub struct SignedRoleAttestation {
200 pub payload: RoleAttestation,
201 pub signature: Vec<u8>,
202 pub key_id: u32,
203}
204
205#[derive(CandidType, Clone, Debug, Deserialize)]
210pub struct InternalInvocationProofRequest {
211 pub subject: Principal,
212 pub role: CanisterRole,
213 #[serde(default)]
214 pub subnet_id: Option<Principal>,
215 pub audience: Principal,
216 pub audience_method: String,
217 pub ttl_secs: u64,
218 #[serde(default)]
219 pub metadata: Option<RootRequestMetadata>,
220}
221
222#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
227pub struct InternalInvocationProofPayloadV1 {
228 pub subject: Principal,
229 pub role: CanisterRole,
230 #[serde(default)]
231 pub subnet_id: Option<Principal>,
232 pub audience: Principal,
233 pub audience_method: String,
234 pub issued_at: u64,
235 pub expires_at: u64,
236 pub epoch: u64,
237}
238
239#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
244pub struct SignedInternalInvocationProofV1 {
245 pub payload: InternalInvocationProofPayloadV1,
246 pub signature: Vec<u8>,
247 pub key_id: u32,
248}
249
250#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
255pub struct CanicInternalCallHeaderV1 {
256 pub target_canister: Principal,
257 pub target_method: String,
258}
259
260#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
265pub struct CanicInternalCallEnvelopeV1 {
266 pub version: u16,
267 pub header: CanicInternalCallHeaderV1,
268 pub proof: SignedInternalInvocationProofV1,
269 pub args: Vec<u8>,
270}
271
272#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
277pub enum AttestationKeyStatus {
278 Current,
279 Previous,
280}
281
282#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
287pub struct AttestationKey {
288 pub key_id: u32,
289 pub public_key: Vec<u8>,
290 pub key_name: String,
291 pub key_hash: [u8; 32],
292 pub status: AttestationKeyStatus,
293 #[serde(default)]
294 pub valid_from: Option<u64>,
295 #[serde(default)]
296 pub valid_until: Option<u64>,
297}
298
299#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
304pub struct AttestationKeySet {
305 pub root_pid: Principal,
306 pub generated_at: u64,
307 pub keys: Vec<AttestationKey>,
308}
309
310#[cfg(test)]
311mod tests {
312 #[test]
313 fn auth_dtos_remain_passive_boundary_types() {
314 let source = include_str!("auth.rs");
315 let production_source = source
316 .split("#[cfg(test)]")
317 .next()
318 .expect("production source exists");
319
320 for marker in [
321 "impl DelegatedToken",
322 "impl DelegatedTokenClaims",
323 "impl RoleAttestation",
324 "impl SignedRoleAttestation",
325 "impl InternalInvocationProofPayloadV1",
326 "impl SignedInternalInvocationProofV1",
327 "impl CanicInternalCallEnvelopeV1",
328 "fn verify",
329 "fn sign",
330 "fn resolve",
331 "fn replay",
332 "fn consume",
333 "fn policy",
334 "fn validate",
335 ] {
336 assert!(
337 !production_source.contains(marker),
338 "auth DTOs must stay passive; found marker `{marker}`"
339 );
340 }
341 }
342}