Skip to content

Commit 61459ec

Browse files
committed
Cleanup.
1 parent 55af3a7 commit 61459ec

File tree

9 files changed

+883
-670
lines changed

9 files changed

+883
-670
lines changed

Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/certificates/builder.rs

Lines changed: 13 additions & 255 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ use std::collections::HashMap;
33
use accounts::{Account, KeyPair};
44
use asn1::SubjectPublicKeyInfo;
55
use crypto::bigint::U256;
6-
use crypto::prelude::{CryptoSignerWithOptions, ExposeSecret, SignatureEncoding};
7-
use x509::certificates::{Certificate as X509Certificate, CertificateBuilder as X509CertificateBuilder, Extension};
6+
use crypto::prelude::{CryptoSignerWithOptions, SignatureEncoding};
7+
use x509::certificates::{CertificateBuilder as X509CertificateBuilder, Extension};
88
use x509::DistinguishedName;
99

1010
use crate::asn1::utils::get_sensitive_attribute_oid;
1111
use crate::asn1::KYC_ATTRIBUTES_EXTENSION_OID;
12-
use crate::certificates::error::CertificateError;
13-
use crate::kyc_schema::{Attribute, AttributeBuilder, KYCAttributes};
14-
use crate::sensitive_attributes::{SensitiveAttribute, SensitiveAttributeBuilder};
12+
use crate::certificates::{Certificate, CertificateError};
13+
use crate::kyc_schema::{AttributeBuilder, KYCAttributes};
14+
use crate::sensitive_attributes::SensitiveAttributeBuilder;
1515

1616
/// Extended certificate builder that supports KYC attributes.
1717
///
@@ -140,14 +140,10 @@ impl CertificateBuilder {
140140
/// This method creates the X.509 certificate and includes any KYC attributes
141141
/// as a custom extension. Sensitive attributes are encrypted using the
142142
/// subject's keypair.
143-
pub fn build<T: KeyPair, S>(
144-
mut self,
145-
subject_keypair: &T,
146-
signing_keypair: &T,
147-
) -> Result<Certificate, CertificateError>
143+
pub fn build<T, S>(mut self, subject_keypair: &T, signing_keypair: &T) -> Result<Certificate, CertificateError>
148144
where
149145
Account<T>: TryFrom<accounts::Accountable<T>, Error = accounts::AccountError>,
150-
T: CryptoSignerWithOptions<S> + 'static,
146+
T: KeyPair + CryptoSignerWithOptions<S> + 'static,
151147
S: SignatureEncoding,
152148
{
153149
// If we have KYC attributes, add them as an extension
@@ -212,119 +208,12 @@ impl Default for CertificateBuilder {
212208
}
213209
}
214210

215-
/// Extended certificate that supports KYC attributes
216-
#[derive(Debug, Clone)]
217-
pub struct Certificate {
218-
/// The underlying X.509 certificate
219-
inner: X509Certificate,
220-
/// Parsed KYC attributes from the certificate
221-
kyc_attributes: KYCAttributes,
222-
// TODO: Fix dyn KeyPair issue
223-
// subject_keypair: Option<Box<dyn KeyPair>>,
224-
}
225-
226-
impl Certificate {
227-
/// Create a new certificate wrapper
228-
pub fn new(x509_cert: X509Certificate) -> Self {
229-
let kyc_attributes = Self::parse_kyc_attributes(&x509_cert);
230-
231-
Self {
232-
inner: x509_cert,
233-
kyc_attributes,
234-
// subject_keypair: None,
235-
}
236-
}
237-
238-
/// Get the underlying X.509 certificate
239-
pub fn to_x509(&self) -> &X509Certificate {
240-
&self.inner
241-
}
242-
243-
/// Get the parsed KYC attributes
244-
pub fn kyc_attributes(&self) -> &KYCAttributes {
245-
&self.kyc_attributes
246-
}
247-
248-
/// Get a specific KYC attribute by name
249-
pub fn get_kyc_attribute(&self, name: &str) -> Option<&Attribute> {
250-
let oid = get_sensitive_attribute_oid(name).ok()?;
251-
self.kyc_attributes.find_by_object_identifier(&oid)
252-
}
253-
254-
/// Decrypt a sensitive KYC attribute value
255-
pub fn decrypt_kyc_attribute<T: KeyPair>(&self, name: &str, keypair: &T) -> Result<Vec<u8>, CertificateError>
256-
where
257-
Account<T>: TryFrom<accounts::Accountable<T>, Error = accounts::AccountError>,
258-
{
259-
let attribute = self
260-
.get_kyc_attribute(name)
261-
.ok_or_else(|| CertificateError::AttributeNotFound { name: name.to_string() })?;
262-
263-
if !attribute.is_sensitive() {
264-
return Err(CertificateError::InvalidAttributeValue {
265-
name: name.to_string(),
266-
reason: "Attribute is not sensitive".to_string(),
267-
});
268-
}
269-
270-
// Decode the sensitive attribute from DER
271-
let sensitive_attr: SensitiveAttribute = rasn::der::decode(attribute.as_ref())?;
272-
273-
// Decrypt the value
274-
let decrypted = sensitive_attr.decrypt(keypair)?;
275-
Ok(decrypted.expose_secret().clone())
276-
}
277-
278-
/// Get a plain text KYC attribute value
279-
pub fn get_plain_kyc_attribute(&self, name: &str) -> Result<Vec<u8>, CertificateError> {
280-
let attribute = self
281-
.get_kyc_attribute(name)
282-
.ok_or_else(|| CertificateError::AttributeNotFound { name: name.to_string() })?;
283-
284-
if attribute.is_sensitive() {
285-
return Err(CertificateError::InvalidAttributeValue {
286-
name: name.to_string(),
287-
reason: "Attribute is sensitive and requires decryption".to_string(),
288-
});
289-
}
290-
291-
Ok(attribute.as_ref().to_vec())
292-
}
293-
294-
/// Parse KYC attributes from an X.509 certificate
295-
fn parse_kyc_attributes(x509_cert: &X509Certificate) -> KYCAttributes {
296-
// Try to find the KYC attributes extension
297-
if let Some(extension) = x509_cert.get_extension(KYC_ATTRIBUTES_EXTENSION_OID.to_string()) {
298-
// Try to decode the extension value
299-
if let Ok(kyc_attrs) = rasn::der::decode::<KYCAttributes>(extension.value.as_bytes()) {
300-
return kyc_attrs;
301-
}
302-
}
303-
304-
// Return empty attributes if not found or parsing failed
305-
KYCAttributes::new()
306-
}
307-
308-
/// Check if the certificate has any KYC attributes
309-
pub fn has_kyc_attributes(&self) -> bool {
310-
!self.kyc_attributes.is_empty()
311-
}
312-
313-
/// Get the number of KYC attributes
314-
pub fn kyc_attribute_count(&self) -> usize {
315-
self.kyc_attributes.count()
316-
}
317-
}
318-
319211
#[cfg(test)]
320212
mod tests {
321-
use accounts::Account;
322213
use x509::certificates::ExtensionBuilder;
323-
use x509::utils::create_dn;
324214
use x509::DistinguishedName;
325215

326216
use super::*;
327-
use crate::testing::create_account_from_seed;
328217

329218
const TEST_ATTRIBUTES: &[(&str, &str, bool)] = &[
330219
("fullName", "John Doe", false),
@@ -334,34 +223,17 @@ mod tests {
334223
("phoneNumber", "+1-555-123-4567", false),
335224
];
336225

337-
/// Helper function to create a test X.509 certificate.
338-
fn create_test_x509_cert() -> X509Certificate {
339-
// Create a minimal X.509 certificate for testing
340-
let subject_dn = create_dn(&[(x509::oids::CN, "Test")]).unwrap();
341-
let account = create_account_from_seed::<accounts::KeyECDSASECP256K1>(0);
342-
let public_key = account.keypair.to_public_key().unwrap();
343-
344-
X509CertificateBuilder::new()
345-
.with_subject_dn(subject_dn.clone())
346-
.with_issuer_dn(subject_dn)
347-
.with_subject_public_key(public_key.into())
348-
.with_serial_number(U256::from(1u64))
349-
.with_validity_days(365)
350-
.build(&account.keypair)
351-
.unwrap()
352-
}
353-
354226
#[test]
355227
fn test_certificate_builder_creation() {
356228
let builders = [
357-
("new", CertificateBuilder::new()),
358-
("for_end_entity", CertificateBuilder::for_end_entity()),
359-
("for_ca", CertificateBuilder::for_ca()),
360-
("default", CertificateBuilder::default()),
229+
CertificateBuilder::new(),
230+
CertificateBuilder::for_end_entity(),
231+
CertificateBuilder::for_ca(),
232+
CertificateBuilder::default(),
361233
];
362234

363-
for (name, builder) in builders {
364-
assert!(builder.kyc_attributes.is_empty(), "Builder {name} should have empty attributes");
235+
for builder in builders {
236+
assert!(builder.kyc_attributes.is_empty());
365237
}
366238
}
367239

@@ -417,118 +289,4 @@ mod tests {
417289
assert!(matches!(result.unwrap_err(), CertificateError::Asn1Error { .. }));
418290
}
419291
}
420-
421-
#[test]
422-
fn test_certificate_without_kyc_attributes() {
423-
let cert = Certificate::new(create_test_x509_cert());
424-
assert!(!cert.has_kyc_attributes());
425-
assert_eq!(cert.kyc_attribute_count(), 0);
426-
assert!(cert.get_kyc_attribute("fullName").is_none());
427-
428-
// Test Certificate.to_x509
429-
let x509_cert = cert.to_x509();
430-
// Just check that we can access the X509 certificate
431-
assert!(x509_cert
432-
.get_extension(KYC_ATTRIBUTES_EXTENSION_OID.to_string())
433-
.is_none());
434-
435-
// Test Certificate.kyc_attributes
436-
let kyc_attrs = cert.kyc_attributes();
437-
assert_eq!(kyc_attrs.count(), 0);
438-
}
439-
440-
#[test]
441-
fn test_certificate_attribute_errors() {
442-
let cert = Certificate::new(create_test_x509_cert());
443-
let result = cert.get_plain_kyc_attribute("nonExistent");
444-
assert!(result.is_err());
445-
assert!(matches!(result.unwrap_err(), CertificateError::AttributeNotFound { .. }));
446-
}
447-
448-
fn test_certificate_building_functionality<T, S>(account: Account<T>)
449-
where
450-
Account<T>: TryFrom<accounts::Accountable<T>, Error = accounts::AccountError>,
451-
T: KeyPair + CryptoSignerWithOptions<S> + 'static,
452-
S: SignatureEncoding,
453-
{
454-
let subject_dn = x509::utils::create_dn(&[(x509::oids::CN, "Test Subject")]).unwrap();
455-
let public_key = account.keypair.to_public_key().unwrap();
456-
let mut builder = CertificateBuilder::for_end_entity()
457-
.with_subject_dn(subject_dn.clone())
458-
.with_issuer_dn(subject_dn)
459-
.with_serial_number(U256::from(12345u64))
460-
.with_validity_days(365)
461-
.with_subject_public_key(public_key.into());
462-
463-
// Add test attributes
464-
for (name, value, sensitive) in TEST_ATTRIBUTES.iter().take(2) {
465-
builder = if *sensitive {
466-
builder.with_sensitive_attribute(name, value).unwrap()
467-
} else {
468-
builder.with_plain_attribute(name, value).unwrap()
469-
};
470-
}
471-
472-
let certificate = builder.build(&account.keypair, &account.keypair).unwrap();
473-
474-
// Verify certificate has KYC attributes
475-
assert!(certificate.has_kyc_attributes());
476-
assert_eq!(certificate.kyc_attribute_count(), 2);
477-
478-
// Test Certificate.kyc_attributes() method when KYC attributes are present
479-
let kyc_attrs = certificate.kyc_attributes();
480-
assert_eq!(kyc_attrs.count(), 2);
481-
482-
// Test both plain and sensitive attributes
483-
for (name, value, sensitive) in TEST_ATTRIBUTES.iter().take(2) {
484-
if *sensitive {
485-
let decrypted = certificate
486-
.decrypt_kyc_attribute(name, &account.keypair)
487-
.unwrap();
488-
assert_eq!(decrypted, value.as_bytes());
489-
} else {
490-
let plain = certificate.get_plain_kyc_attribute(name).unwrap();
491-
assert_eq!(plain, value.as_bytes());
492-
}
493-
}
494-
495-
// Test error cases
496-
assert!(certificate.get_kyc_attribute("nonExistent").is_none());
497-
}
498-
499-
crate::test_all_key_types!(test_certificate_building, test_certificate_building_functionality);
500-
501-
fn test_certificate_attribute_type_errors<T, S>(account: Account<T>)
502-
where
503-
Account<T>: TryFrom<accounts::Accountable<T>, Error = accounts::AccountError>,
504-
T: KeyPair + CryptoSignerWithOptions<S> + 'static,
505-
S: SignatureEncoding,
506-
{
507-
let subject_dn = x509::utils::create_dn(&[(x509::oids::CN, "Test Subject")]).unwrap();
508-
let public_key = account.keypair.to_public_key().unwrap();
509-
let builder = CertificateBuilder::for_end_entity()
510-
.with_subject_dn(subject_dn.clone())
511-
.with_issuer_dn(subject_dn)
512-
.with_serial_number(U256::from(12345u64))
513-
.with_validity_days(365)
514-
.with_subject_public_key(public_key.into())
515-
.with_plain_attribute("fullName", "Jane Smith")
516-
.unwrap()
517-
.with_sensitive_attribute("email", "jane@example.com")
518-
.unwrap();
519-
520-
let certificate = builder.build(&account.keypair, &account.keypair).unwrap();
521-
522-
// Test trying to decrypt a plain attribute
523-
let result = certificate.decrypt_kyc_attribute("fullName", &account.keypair);
524-
assert!(result.is_err());
525-
assert!(matches!(result.unwrap_err(), CertificateError::InvalidAttributeValue { .. }));
526-
527-
// Test trying to get a sensitive attribute as plain
528-
let result = certificate.get_plain_kyc_attribute("email");
529-
assert!(result.is_err());
530-
assert!(matches!(result.unwrap_err(), CertificateError::InvalidAttributeValue { .. }));
531-
}
532-
533-
crate::test_all_key_types!(test_certificate_type_errors, test_certificate_attribute_type_errors);
534292
}

0 commit comments

Comments
 (0)