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 Canic,
19 Project(String),
20}
21
22#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
27pub struct DelegatedRoleGrant {
28 pub target: CanisterRole,
29 pub scopes: Vec<String>,
30}
31
32#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
37pub struct RootPublicKey {
38 pub root_pid: Principal,
39 pub key_id: String,
40 pub alg: SignatureAlgorithm,
41 pub public_key_sec1: Vec<u8>,
42 pub key_hash: [u8; 32],
43 pub not_before: u64,
44 pub not_after: Option<u64>,
45}
46
47#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
52pub struct RootTrustAnchor {
53 pub root_pid: Principal,
54 pub root_key: RootPublicKey,
55}
56
57#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
62pub enum ShardKeyBinding {
63 IcThresholdEcdsa {
64 key_name_hash: [u8; 32],
65 derivation_path_hash: [u8; 32],
66 },
67}
68
69#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
74pub struct DelegationCert {
75 pub version: u16,
76 pub root_pid: Principal,
77 pub root_key_id: String,
78 pub root_key_hash: [u8; 32],
79 pub alg: SignatureAlgorithm,
80 pub shard_pid: Principal,
81 pub shard_key_id: String,
82 pub shard_public_key_sec1: Vec<u8>,
83 pub shard_key_hash: [u8; 32],
84 pub shard_key_binding: ShardKeyBinding,
85 pub issued_at: u64,
86 pub expires_at: u64,
87 pub max_token_ttl_secs: u64,
88 pub aud: DelegationAudience,
89 pub grants: Vec<DelegatedRoleGrant>,
90}
91
92#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
97pub struct DelegationProof {
98 pub cert: DelegationCert,
99 pub root_sig: Vec<u8>,
100}
101
102#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
107pub struct DelegatedTokenClaims {
108 pub version: u16,
109 pub subject: Principal,
110 pub issuer_shard_pid: Principal,
111 pub cert_hash: [u8; 32],
112 pub issued_at: u64,
113 pub expires_at: u64,
114 pub aud: DelegationAudience,
115 pub grants: Vec<DelegatedRoleGrant>,
116 pub nonce: [u8; 16],
117}
118
119#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
124pub struct DelegatedToken {
125 pub claims: DelegatedTokenClaims,
126 pub proof: DelegationProof,
127 pub shard_sig: Vec<u8>,
128}
129
130#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
135pub struct DelegationProofIssueRequest {
136 #[serde(default)]
137 pub metadata: Option<RootRequestMetadata>,
138 pub shard_pid: Principal,
139 pub aud: DelegationAudience,
140 pub grants: Vec<DelegatedRoleGrant>,
141 pub cert_ttl_secs: u64,
142}
143
144#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
149pub struct DelegatedTokenIssueRequest {
150 #[serde(default)]
151 pub metadata: Option<RootRequestMetadata>,
152 pub proof: DelegationProof,
153 pub subject: Principal,
154 pub aud: DelegationAudience,
155 pub grants: Vec<DelegatedRoleGrant>,
156 pub ttl_secs: u64,
157 pub nonce: [u8; 16],
158}
159
160#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
165pub struct DelegatedTokenMintRequest {
166 #[serde(default)]
167 pub metadata: Option<RootRequestMetadata>,
168 pub subject: Principal,
169 pub aud: DelegationAudience,
170 pub grants: Vec<DelegatedRoleGrant>,
171 pub token_ttl_secs: u64,
172 pub cert_ttl_secs: u64,
173 pub nonce: [u8; 16],
174}
175
176#[derive(CandidType, Clone, Debug, Deserialize)]
181pub struct RoleAttestationRequest {
182 pub subject: Principal,
183 pub role: CanisterRole,
184 #[serde(default)]
185 pub subnet_id: Option<Principal>,
186 pub audience: Principal,
187 pub ttl_secs: u64,
188 pub epoch: u64,
189 #[serde(default)]
190 pub metadata: Option<RootRequestMetadata>,
191}
192
193#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
198pub struct RoleAttestation {
199 pub subject: Principal,
200 pub role: CanisterRole,
201 #[serde(default)]
202 pub subnet_id: Option<Principal>,
203 pub audience: Principal,
204 pub issued_at: u64,
205 pub expires_at: u64,
206 pub epoch: u64,
207}
208
209#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
214pub struct SignedRoleAttestation {
215 pub payload: RoleAttestation,
216 pub signature: Vec<u8>,
217 pub key_id: u32,
218}
219
220#[derive(CandidType, Clone, Debug, Deserialize)]
225pub struct InternalInvocationProofRequest {
226 pub subject: Principal,
227 pub role: CanisterRole,
228 #[serde(default)]
229 pub subnet_id: Option<Principal>,
230 pub audience: Principal,
231 pub audience_method: String,
232 pub ttl_secs: u64,
233 #[serde(default)]
234 pub metadata: Option<RootRequestMetadata>,
235}
236
237#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
242pub struct InternalInvocationProofPayloadV1 {
243 pub subject: Principal,
244 pub role: CanisterRole,
245 #[serde(default)]
246 pub subnet_id: Option<Principal>,
247 pub audience: Principal,
248 pub audience_method: String,
249 pub issued_at: u64,
250 pub expires_at: u64,
251 pub epoch: u64,
252}
253
254#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
259pub struct SignedInternalInvocationProofV1 {
260 pub payload: InternalInvocationProofPayloadV1,
261 pub signature: Vec<u8>,
262 pub key_id: u32,
263}
264
265#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
270pub struct CanicInternalCallHeaderV1 {
271 pub target_canister: Principal,
272 pub target_method: String,
273}
274
275#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
280pub struct CanicInternalCallEnvelopeV1 {
281 pub version: u16,
282 pub header: CanicInternalCallHeaderV1,
283 pub proof: SignedInternalInvocationProofV1,
284 pub args: Vec<u8>,
285}
286
287#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
292pub enum AttestationKeyStatus {
293 Current,
294 Previous,
295}
296
297#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
302pub struct AttestationKey {
303 pub key_id: u32,
304 pub public_key: Vec<u8>,
305 pub key_name: String,
306 pub key_hash: [u8; 32],
307 pub status: AttestationKeyStatus,
308 #[serde(default)]
309 pub valid_from: Option<u64>,
310 #[serde(default)]
311 pub valid_until: Option<u64>,
312}
313
314#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
319pub struct AttestationKeySet {
320 pub root_pid: Principal,
321 pub generated_at: u64,
322 pub keys: Vec<AttestationKey>,
323}
324
325#[cfg(test)]
326mod tests {
327 #[test]
328 fn auth_dtos_remain_passive_boundary_types() {
329 let source = include_str!("auth.rs");
330 let production_source = source
331 .split("#[cfg(test)]")
332 .next()
333 .expect("production source exists");
334
335 for marker in [
336 "impl DelegatedToken",
337 "impl DelegatedTokenClaims",
338 "impl RoleAttestation",
339 "impl SignedRoleAttestation",
340 "impl InternalInvocationProofPayloadV1",
341 "impl SignedInternalInvocationProofV1",
342 "impl CanicInternalCallEnvelopeV1",
343 "fn verify",
344 "fn sign",
345 "fn resolve",
346 "fn replay",
347 "fn consume",
348 "fn policy",
349 "fn validate",
350 ] {
351 assert!(
352 !production_source.contains(marker),
353 "auth DTOs must stay passive; found marker `{marker}`"
354 );
355 }
356 }
357}