ex3_ic_agent/identity/
basic.rs

1use crate::{export::Principal, Identity, Signature};
2
3#[cfg(feature = "pem")]
4use crate::identity::error::PemError;
5
6use ring::signature::{Ed25519KeyPair, KeyPair};
7use simple_asn1::{
8    oid, to_der,
9    ASN1Block::{BitString, ObjectIdentifier, Sequence},
10};
11
12use std::fmt;
13
14/// A Basic Identity which sign using an ED25519 key pair.
15pub struct BasicIdentity {
16    key_pair: Ed25519KeyPair,
17    der_encoded_public_key: Vec<u8>,
18}
19
20impl fmt::Debug for BasicIdentity {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        f.debug_struct("BasicIdentity")
23            .field("der_encoded_public_key", &self.der_encoded_public_key)
24            .finish_non_exhaustive()
25    }
26}
27
28impl BasicIdentity {
29    /// Create a BasicIdentity from reading a PEM file at the path.
30    #[cfg(feature = "pem")]
31    pub fn from_pem_file<P: AsRef<std::path::Path>>(file_path: P) -> Result<Self, PemError> {
32        Self::from_pem(std::fs::File::open(file_path)?)
33    }
34
35    /// Create a BasicIdentity from reading a PEM File from a Reader.
36    #[cfg(feature = "pem")]
37    pub fn from_pem<R: std::io::Read>(pem_reader: R) -> Result<Self, PemError> {
38        let bytes: Vec<u8> = pem_reader
39            .bytes()
40            .collect::<Result<Vec<u8>, std::io::Error>>()?;
41
42        Ok(BasicIdentity::from_key_pair(Ed25519KeyPair::from_pkcs8(
43            pem::parse(&bytes)?.contents(),
44        )?))
45    }
46
47    /// Create a BasicIdentity from a KeyPair from the ring crate.
48    pub fn from_key_pair(key_pair: Ed25519KeyPair) -> Self {
49        let der_encoded_public_key = der_encode_public_key(key_pair.public_key().as_ref().to_vec());
50
51        Self {
52            key_pair,
53            der_encoded_public_key,
54        }
55    }
56}
57
58impl Identity for BasicIdentity {
59    fn sender(&self) -> Result<Principal, String> {
60        Ok(Principal::self_authenticating(&self.der_encoded_public_key))
61    }
62    fn sign(&self, msg: &[u8]) -> Result<Signature, String> {
63        let signature = self.key_pair.sign(msg.as_ref());
64        // At this point we shall validate the signature in this first
65        // skeleton version.
66
67        Ok(Signature {
68            signature: Some(signature.as_ref().to_vec()),
69            public_key: Some(self.der_encoded_public_key.clone()),
70        })
71    }
72}
73
74fn der_encode_public_key(public_key: Vec<u8>) -> Vec<u8> {
75    // see Section 4 "SubjectPublicKeyInfo" in https://tools.ietf.org/html/rfc8410
76
77    let id_ed25519 = oid!(1, 3, 101, 112);
78    let algorithm = Sequence(0, vec![ObjectIdentifier(0, id_ed25519)]);
79    let subject_public_key = BitString(0, public_key.len() * 8, public_key);
80    let subject_public_key_info = Sequence(0, vec![algorithm, subject_public_key]);
81    to_der(&subject_public_key_info).unwrap()
82}