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 #[serde(default)]
142 pub metadata: Option<RootRequestMetadata>,
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 #[serde(default)]
158 pub metadata: Option<RootRequestMetadata>,
159 pub subject: Principal,
160 pub aud: DelegationAudience,
161 pub scopes: Vec<String>,
162 pub token_ttl_secs: u64,
163 pub cert_ttl_secs: u64,
164 pub nonce: [u8; 16],
165}
166
167#[derive(CandidType, Clone, Debug, Deserialize)]
172pub struct RoleAttestationRequest {
173 pub subject: Principal,
174 pub role: CanisterRole,
175 #[serde(default)]
176 pub subnet_id: Option<Principal>,
177 pub audience: Principal,
178 pub ttl_secs: u64,
179 pub epoch: u64,
180 #[serde(default)]
181 pub metadata: Option<RootRequestMetadata>,
182}
183
184#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
189pub struct RoleAttestation {
190 pub subject: Principal,
191 pub role: CanisterRole,
192 #[serde(default)]
193 pub subnet_id: Option<Principal>,
194 pub audience: Principal,
195 pub issued_at: u64,
196 pub expires_at: u64,
197 pub epoch: u64,
198}
199
200#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
205pub struct SignedRoleAttestation {
206 pub payload: RoleAttestation,
207 pub signature: Vec<u8>,
208 pub key_id: u32,
209}
210
211#[derive(CandidType, Clone, Debug, Deserialize)]
216pub struct InternalInvocationProofRequest {
217 pub subject: Principal,
218 pub role: CanisterRole,
219 #[serde(default)]
220 pub subnet_id: Option<Principal>,
221 pub audience: Principal,
222 pub audience_method: String,
223 pub ttl_secs: u64,
224 #[serde(default)]
225 pub metadata: Option<RootRequestMetadata>,
226}
227
228#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
233pub struct InternalInvocationProofPayloadV1 {
234 pub subject: Principal,
235 pub role: CanisterRole,
236 #[serde(default)]
237 pub subnet_id: Option<Principal>,
238 pub audience: Principal,
239 pub audience_method: String,
240 pub issued_at: u64,
241 pub expires_at: u64,
242 pub epoch: u64,
243}
244
245#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
250pub struct SignedInternalInvocationProofV1 {
251 pub payload: InternalInvocationProofPayloadV1,
252 pub signature: Vec<u8>,
253 pub key_id: u32,
254}
255
256#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
261pub struct CanicInternalCallHeaderV1 {
262 pub target_canister: Principal,
263 pub target_method: String,
264}
265
266#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
271pub struct CanicInternalCallEnvelopeV1 {
272 pub version: u16,
273 pub header: CanicInternalCallHeaderV1,
274 pub proof: SignedInternalInvocationProofV1,
275 pub args: Vec<u8>,
276}
277
278#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
283pub enum AttestationKeyStatus {
284 Current,
285 Previous,
286}
287
288#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
293pub struct AttestationKey {
294 pub key_id: u32,
295 pub public_key: Vec<u8>,
296 pub key_name: String,
297 pub key_hash: [u8; 32],
298 pub status: AttestationKeyStatus,
299 #[serde(default)]
300 pub valid_from: Option<u64>,
301 #[serde(default)]
302 pub valid_until: Option<u64>,
303}
304
305#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
310pub struct AttestationKeySet {
311 pub root_pid: Principal,
312 pub generated_at: u64,
313 pub keys: Vec<AttestationKey>,
314}
315
316#[cfg(test)]
317mod tests {
318 #[test]
319 fn auth_dtos_remain_passive_boundary_types() {
320 let source = include_str!("auth.rs");
321 let production_source = source
322 .split("#[cfg(test)]")
323 .next()
324 .expect("production source exists");
325
326 for marker in [
327 "impl DelegatedToken",
328 "impl DelegatedTokenClaims",
329 "impl RoleAttestation",
330 "impl SignedRoleAttestation",
331 "impl InternalInvocationProofPayloadV1",
332 "impl SignedInternalInvocationProofV1",
333 "impl CanicInternalCallEnvelopeV1",
334 "fn verify",
335 "fn sign",
336 "fn resolve",
337 "fn replay",
338 "fn consume",
339 "fn policy",
340 "fn validate",
341 ] {
342 assert!(
343 !production_source.contains(marker),
344 "auth DTOs must stay passive; found marker `{marker}`"
345 );
346 }
347 }
348}