use std::sync::Arc;
use crate::{agent::EnvelopeContent, export::Principal};
pub(crate) mod anonymous;
pub(crate) mod basic;
pub(crate) mod delegated;
pub(crate) mod error;
pub(crate) mod info_aware;
pub(crate) mod prime256v1;
pub(crate) mod secp256k1;
#[doc(inline)]
pub use anonymous::AnonymousIdentity;
#[doc(inline)]
pub use basic::BasicIdentity;
#[doc(inline)]
pub use delegated::DelegatedIdentity;
#[doc(inline)]
pub use error::DelegationError;
#[doc(inline)]
pub use ic_transport_types::{Delegation, SenderInfo, SignedDelegation};
#[doc(inline)]
pub use info_aware::InfoAwareIdentity;
#[doc(inline)]
pub use prime256v1::Prime256v1Identity;
#[doc(inline)]
pub use secp256k1::Secp256k1Identity;
#[cfg(feature = "pem")]
#[doc(inline)]
pub use error::PemError;
#[derive(Clone, Debug)]
pub struct Signature {
pub public_key: Option<Vec<u8>>,
pub signature: Option<Vec<u8>>,
pub delegations: Option<Vec<SignedDelegation>>,
}
pub trait Identity: Send + Sync {
fn sender(&self) -> Result<Principal, String>;
fn public_key(&self) -> Option<Vec<u8>>;
fn sign(&self, content: &EnvelopeContent) -> Result<Signature, String>;
fn sign_delegation(&self, content: &Delegation) -> Result<Signature, String> {
let _ = content; Err(String::from("unsupported"))
}
fn sign_arbitrary(&self, content: &[u8]) -> Result<Signature, String> {
let _ = content; Err(String::from("unsupported"))
}
fn delegation_chain(&self) -> Vec<SignedDelegation> {
vec![]
}
fn sender_info(&self) -> Option<SenderInfo> {
None
}
}
macro_rules! delegating_impl {
($implementor:ty, $name:ident => $self_expr:expr) => {
impl Identity for $implementor {
fn sender(&$name) -> Result<Principal, String> {
$self_expr.sender()
}
fn public_key(&$name) -> Option<Vec<u8>> {
$self_expr.public_key()
}
fn sign(&$name, content: &EnvelopeContent) -> Result<Signature, String> {
$self_expr.sign(content)
}
fn sign_delegation(&$name, content: &Delegation) -> Result<Signature, String> {
$self_expr.sign_delegation(content)
}
fn sign_arbitrary(&$name, content: &[u8]) -> Result<Signature, String> {
$self_expr.sign_arbitrary(content)
}
fn delegation_chain(&$name) -> Vec<SignedDelegation> {
$self_expr.delegation_chain()
}
fn sender_info(&$name) -> Option<SenderInfo> {
$self_expr.sender_info()
}
}
};
}
delegating_impl!(Box<dyn Identity>, self => **self);
delegating_impl!(Arc<dyn Identity>, self => **self);
delegating_impl!(&dyn Identity, self => *self);
#[cfg(feature = "pem")]
fn parse_ec_pkcs8_key_bytes(
der_bytes: &[u8],
expected_curve: pkcs8::der::asn1::ObjectIdentifier,
curve_name: &str,
) -> Result<Vec<u8>, error::PemError> {
use pkcs8::{
der::{Decode, Encode},
PrivateKeyInfo,
};
let mut truncated: Vec<u8>;
let pki = match PrivateKeyInfo::from_der(der_bytes) {
Ok(pki) => pki,
Err(e) => {
truncated = der_bytes.to_vec();
if truncated.len() >= 52 && truncated[48..52] == *b"\xA1\x23\x03\x21" {
truncated.truncate(48);
truncated[1] = 46;
truncated[4] = 0;
PrivateKeyInfo::from_der(&truncated).map_err(|_| e)?
} else {
return Err(e.into());
}
}
};
if pki.algorithm.oid != elliptic_curve::ALGORITHM_OID {
return Err(error::PemError::InvalidPrivateKey(format!(
"expected EC algorithm OID {}, found {}",
elliptic_curve::ALGORITHM_OID,
pki.algorithm.oid,
)));
}
let curve_oid = pki
.algorithm
.parameters_oid()
.map_err(|_| pkcs8::Error::KeyMalformed)?;
if curve_oid != expected_curve {
return Err(error::PemError::UnsupportedKeyCurve(
curve_name.to_string(),
curve_oid.to_der().unwrap_or_default(),
));
}
Ok(pki.private_key.to_vec())
}