cpop_protocol/
identity.rs1use crate::error::{Error, Result};
4use const_oid::AssociatedOid;
5use ed25519_dalek::{Signer, SigningKey, VerifyingKey};
6use rand::rngs::OsRng;
7use rand::RngCore;
8use serde::{Deserialize, Serialize};
9use sha2::{Digest, Sha256};
10use signature::Keypair;
11use spki::{
12 AlgorithmIdentifierOwned, DynSignatureAlgorithmIdentifier, EncodePublicKey, ObjectIdentifier,
13 SignatureBitStringEncoding, SubjectPublicKeyInfoOwned,
14};
15use std::str::FromStr;
16use x509_cert::builder::{Builder, RequestBuilder};
17use x509_cert::der::asn1::{BitString, OctetString};
18use x509_cert::der::{Encode, FixedTag, Tag};
19use x509_cert::ext::pkix::SubjectKeyIdentifier;
20use x509_cert::ext::{AsExtension, Extension};
21use x509_cert::name::Name;
22use zeroize::Zeroizing;
23
24const ED25519_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.101.112");
25
26#[derive(Clone, Debug)]
28pub struct X509VerifyingKey(pub VerifyingKey);
29
30impl EncodePublicKey for X509VerifyingKey {
31 fn to_public_key_der(&self) -> spki::Result<spki::der::Document> {
32 let spki = SubjectPublicKeyInfoOwned {
33 algorithm: AlgorithmIdentifierOwned {
34 oid: ED25519_OID,
35 parameters: None,
36 },
37 subject_public_key: BitString::from_bytes(self.0.as_bytes())?,
38 };
39 let der = spki.to_der().map_err(|_| spki::Error::KeyMalformed)?;
40 spki::der::Document::try_from(der.as_slice()).map_err(|_| spki::Error::KeyMalformed)
41 }
42}
43
44pub struct X509Signer(pub SigningKey);
46
47impl Keypair for X509Signer {
48 type VerifyingKey = X509VerifyingKey;
49 fn verifying_key(&self) -> Self::VerifyingKey {
50 X509VerifyingKey(self.0.verifying_key())
51 }
52}
53
54impl DynSignatureAlgorithmIdentifier for X509Signer {
55 fn signature_algorithm_identifier(&self) -> spki::Result<AlgorithmIdentifierOwned> {
56 Ok(AlgorithmIdentifierOwned {
57 oid: ED25519_OID,
58 parameters: None,
59 })
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct X509Signature(pub ed25519_dalek::Signature);
66
67impl signature::SignatureEncoding for X509Signature {
68 type Repr = [u8; 64];
69 fn to_bytes(&self) -> Self::Repr {
70 self.0.to_bytes()
71 }
72}
73
74impl TryFrom<&[u8]> for X509Signature {
75 type Error = signature::Error;
76 fn try_from(bytes: &[u8]) -> std::result::Result<Self, Self::Error> {
77 ed25519_dalek::Signature::from_slice(bytes)
78 .map(X509Signature)
79 .map_err(|_| signature::Error::new())
80 }
81}
82
83impl From<X509Signature> for [u8; 64] {
84 fn from(sig: X509Signature) -> Self {
85 sig.0.to_bytes()
86 }
87}
88
89impl Signer<X509Signature> for X509Signer {
90 fn try_sign(&self, msg: &[u8]) -> std::result::Result<X509Signature, signature::Error> {
91 Ok(X509Signature(self.0.sign(msg)))
92 }
93}
94
95impl SignatureBitStringEncoding for X509Signature {
96 fn to_bitstring(&self) -> std::result::Result<BitString, x509_cert::der::Error> {
97 BitString::from_bytes(&self.0.to_bytes())
98 }
99}
100
101#[derive(Clone, Debug, PartialEq, Eq)]
103pub struct Capability(pub OctetString);
104
105impl AssociatedOid for Capability {
106 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.6.1.4.1.54066.1.1");
107}
108
109impl Encode for Capability {
110 fn encoded_len(&self) -> x509_cert::der::Result<x509_cert::der::Length> {
111 self.0.encoded_len()
112 }
113 fn encode(&self, encoder: &mut impl x509_cert::der::Writer) -> x509_cert::der::Result<()> {
114 self.0.encode(encoder)
115 }
116}
117
118impl FixedTag for Capability {
119 const TAG: Tag = Tag::OctetString;
120}
121
122impl AsExtension for Capability {
123 fn critical(&self, _: &x509_cert::name::RdnSequence, _: &[Extension]) -> bool {
124 false
125 }
126}
127
128#[derive(Debug, Serialize, Deserialize)]
129pub struct EnrollmentRequest {
130 pub user_id: String,
131 pub public_key_cose: Vec<u8>,
133 pub hardware_attestation: Vec<u8>,
135}
136
137pub struct IdentityManager {
138 signer: X509Signer,
139}
140
141impl IdentityManager {
142 pub fn generate() -> Self {
143 let mut bytes = Zeroizing::new([0u8; 32]);
144 OsRng.fill_bytes(bytes.as_mut());
145 Self {
146 signer: X509Signer(SigningKey::from_bytes(&bytes)),
147 }
148 }
149
150 pub fn from_secret_key(bytes: &[u8; 32]) -> Self {
151 Self {
152 signer: X509Signer(SigningKey::from_bytes(bytes)),
153 }
154 }
155
156 pub fn signing_key(&self) -> &SigningKey {
157 &self.signer.0
158 }
159
160 pub fn generate_csr(&self, subject_dn: &str) -> Result<Vec<u8>> {
162 let subject = Name::from_str(subject_dn)
163 .map_err(|e| Error::Validation(format!("Invalid Subject DN: {}", e)))?;
164
165 let mut builder = RequestBuilder::new(subject, &self.signer)
166 .map_err(|e| Error::Crypto(format!("CSR builder error: {}", e)))?;
167
168 let public_key_bytes = self.signer.0.verifying_key().to_bytes();
169 let hash = Sha256::digest(public_key_bytes);
170 let ski = SubjectKeyIdentifier(
171 OctetString::new(hash.to_vec())
172 .map_err(|e| Error::Crypto(format!("Failed to create OctetString: {}", e)))?,
173 );
174 builder
175 .add_extension(&ski)
176 .map_err(|e| Error::Crypto(format!("Failed to add SKI extension: {}", e)))?;
177
178 let pop_cap =
179 Capability(OctetString::new(vec![0x01]).map_err(|e| Error::Crypto(e.to_string()))?);
180 builder
181 .add_extension(&pop_cap)
182 .map_err(|e| Error::Crypto(format!("Failed to add CPoP extension: {}", e)))?;
183
184 let csr = builder
185 .build::<X509Signature>()
186 .map_err(|e| Error::Crypto(format!("CSR signing error: {}", e)))?;
187
188 csr.to_der()
189 .map_err(|e| Error::Crypto(format!("DER encoding error: {}", e)))
190 }
191
192 pub fn create_enrollment_request(
194 &self,
195 user_id: &str,
196 hardware_attestation: &[u8],
197 ) -> Result<EnrollmentRequest> {
198 let public_key_cose = self.signer.0.verifying_key().to_bytes().to_vec();
199
200 Ok(EnrollmentRequest {
201 user_id: user_id.to_string(),
202 public_key_cose,
203 hardware_attestation: hardware_attestation.to_vec(),
204 })
205 }
206}