ic_agent/identity/
info_aware.rs1use candid::Principal;
2use pkcs8::{
3 der::{Decode, SliceReader},
4 spki::SubjectPublicKeyInfoRef,
5};
6
7use ic_transport_types::SenderInfo;
8
9use crate::{
10 agent::{EnvelopeContent, IC_ROOT_KEY},
11 Signature,
12};
13
14use super::{
15 delegated::{parse_canister_sig_pubkey, verify_canister_sig, CANISTER_SIG_OID},
16 error::DelegationError,
17 Delegation, Identity, SignedDelegation,
18};
19
20const SENDER_INFO_DOMAIN_SEP: &[u8; 15] = b"\x0Eic-sender-info";
22
23pub struct InfoAwareIdentity<I: Identity> {
28 inner: I,
29 info: Vec<u8>,
30 signer: Principal,
31 sig: Vec<u8>,
32}
33
34impl<I: Identity> InfoAwareIdentity<I> {
35 pub fn new(inner: I, info: Vec<u8>, sig: Vec<u8>) -> Result<Self, DelegationError> {
40 Self::new_impl(inner, info, sig, IC_ROOT_KEY)
41 }
42
43 pub fn new_with_root_key(
45 inner: I,
46 info: Vec<u8>,
47 sig: Vec<u8>,
48 root_key: &[u8],
49 ) -> Result<Self, DelegationError> {
50 Self::new_impl(inner, info, sig, root_key)
51 }
52
53 pub fn new_unchecked(inner: I, info: Vec<u8>, sig: Vec<u8>) -> Result<Self, DelegationError> {
58 let (signer, _seed) = parse_canister_pubkey(&inner)?;
59 Ok(Self {
60 inner,
61 info,
62 signer,
63 sig,
64 })
65 }
66
67 fn new_impl(
68 inner: I,
69 info: Vec<u8>,
70 sig: Vec<u8>,
71 root_key: &[u8],
72 ) -> Result<Self, DelegationError> {
73 let (signer, seed) = parse_canister_pubkey(&inner)?;
74 let mut payload = Vec::with_capacity(SENDER_INFO_DOMAIN_SEP.len() + info.len());
75 payload.extend_from_slice(SENDER_INFO_DOMAIN_SEP);
76 payload.extend_from_slice(&info);
77 verify_canister_sig(&payload, &sig, signer, &seed, root_key)?;
78 Ok(Self {
79 inner,
80 info,
81 signer,
82 sig,
83 })
84 }
85}
86
87fn parse_canister_pubkey<I: Identity>(inner: &I) -> Result<(Principal, Vec<u8>), DelegationError> {
89 let pubkey = inner.public_key().ok_or(DelegationError::Parse)?;
90 let spki = SubjectPublicKeyInfoRef::decode(
91 &mut SliceReader::new(&pubkey).map_err(|_| DelegationError::Parse)?,
92 )
93 .map_err(|_| DelegationError::Parse)?;
94 if spki.algorithm.oid != CANISTER_SIG_OID {
95 return Err(DelegationError::UnknownAlgorithm);
96 }
97 parse_canister_sig_pubkey(spki.subject_public_key.raw_bytes())
98}
99
100impl<I: Identity> Identity for InfoAwareIdentity<I> {
101 fn sender(&self) -> Result<Principal, String> {
102 self.inner.sender()
103 }
104
105 fn public_key(&self) -> Option<Vec<u8>> {
106 self.inner.public_key()
107 }
108
109 fn sign(&self, content: &EnvelopeContent) -> Result<Signature, String> {
110 self.inner.sign(content)
111 }
112
113 fn sign_delegation(&self, content: &Delegation) -> Result<Signature, String> {
114 self.inner.sign_delegation(content)
115 }
116
117 fn sign_arbitrary(&self, content: &[u8]) -> Result<Signature, String> {
118 self.inner.sign_arbitrary(content)
119 }
120
121 fn delegation_chain(&self) -> Vec<SignedDelegation> {
122 self.inner.delegation_chain()
123 }
124
125 fn sender_info(&self) -> Option<SenderInfo> {
126 Some(SenderInfo {
127 info: self.info.clone(),
128 signer: self.signer.as_slice().to_vec(),
129 sig: self.sig.clone(),
130 })
131 }
132}