Improve self-signed certificates (#207)
Adds support for: - A hierarchical SubjectName field. - Certificate extensions.
This commit is contained in:
Generated
+2
-2
@@ -1047,9 +1047,9 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "x509"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9335b8ff50b6a0de184b3eeb11fdce74224e3af90ca7265012512e73fc999d1a"
|
||||
checksum = "ca3cec94c3999f31341553f358ef55f65fc031291a022cd42ec0ce7219560c76"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"cookie-factory",
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ sha-1 = "0.9"
|
||||
sha2 = "0.9"
|
||||
subtle = "2"
|
||||
subtle-encoding = "0.5"
|
||||
x509 = "0.1.2"
|
||||
x509 = "0.2"
|
||||
x509-parser = "0.9"
|
||||
zeroize = "1"
|
||||
|
||||
|
||||
+20
-6
@@ -49,6 +49,7 @@ use sha2::{Digest, Sha256};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::ops::DerefMut;
|
||||
use x509::{der::Oid, RelativeDistinguishedName};
|
||||
use x509_parser::{parse_x509_certificate, x509::SubjectPublicKeyInfo};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
@@ -337,19 +338,21 @@ impl<'a> TryFrom<&'a [u8]> for Certificate {
|
||||
impl Certificate {
|
||||
/// Creates a new self-signed certificate for the given key. Writes the resulting
|
||||
/// certificate to the slot before returning it.
|
||||
pub fn generate_self_signed(
|
||||
///
|
||||
/// `extensions` is optional; if empty, no extensions will be included. Due to the
|
||||
/// need for an `O: Oid` type parameter, users who do not have any extensions should
|
||||
/// use the workaround `let extensions: &[x509::Extension<'_, &[u64]>] = &[];`.
|
||||
pub fn generate_self_signed<O: Oid>(
|
||||
yubikey: &mut YubiKey,
|
||||
key: SlotId,
|
||||
serial: impl Into<Serial>,
|
||||
not_after: Option<DateTime<Utc>>,
|
||||
subject: String,
|
||||
subject: &[RelativeDistinguishedName<'_>],
|
||||
subject_pki: PublicKeyInfo,
|
||||
extensions: &[x509::Extension<'_, O>],
|
||||
) -> Result<Self, Error> {
|
||||
let serial = serial.into();
|
||||
|
||||
// Issuer and subject are the same in self-signed certificates
|
||||
let issuer = subject.clone();
|
||||
|
||||
let mut tbs_cert = Buffer::new(Vec::with_capacity(CB_OBJ_MAX));
|
||||
|
||||
let signature_algorithm = match subject_pki.algorithm() {
|
||||
@@ -361,11 +364,13 @@ impl Certificate {
|
||||
x509::write::tbs_certificate(
|
||||
&serial.to_bytes(),
|
||||
&signature_algorithm,
|
||||
&issuer,
|
||||
// Issuer and subject are the same in self-signed certificates.
|
||||
&subject,
|
||||
Utc::now(),
|
||||
not_after,
|
||||
&subject,
|
||||
&subject_pki,
|
||||
&extensions,
|
||||
),
|
||||
tbs_cert.deref_mut(),
|
||||
)
|
||||
@@ -425,6 +430,15 @@ impl Certificate {
|
||||
)
|
||||
.expect("can serialize to Vec");
|
||||
|
||||
let (issuer, subject) = parse_x509_certificate(&data)
|
||||
.map(|(_, cert)| {
|
||||
(
|
||||
cert.tbs_certificate.issuer.to_string(),
|
||||
cert.tbs_certificate.subject.to_string(),
|
||||
)
|
||||
})
|
||||
.expect("We just serialized this correctly");
|
||||
|
||||
let cert = Certificate {
|
||||
serial,
|
||||
issuer,
|
||||
|
||||
@@ -10,6 +10,7 @@ use rsa::{hash::Hash::SHA2_256, PaddingScheme, PublicKey};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::convert::TryInto;
|
||||
use std::{env, sync::Mutex};
|
||||
use x509::RelativeDistinguishedName;
|
||||
use yubikey_piv::{
|
||||
certificate::{Certificate, PublicKeyInfo},
|
||||
key::{self, AlgorithmId, Key, RetiredSlotId, SlotId},
|
||||
@@ -132,13 +133,15 @@ fn generate_self_signed_cert(algorithm: AlgorithmId) -> Certificate {
|
||||
getrandom(&mut serial).unwrap();
|
||||
|
||||
// Generate a self-signed certificate for the new key.
|
||||
let extensions: &[x509::Extension<'_, &[u64]>] = &[];
|
||||
let cert_result = Certificate::generate_self_signed(
|
||||
&mut yubikey,
|
||||
slot,
|
||||
serial,
|
||||
None,
|
||||
"testSubject".to_owned(),
|
||||
&[RelativeDistinguishedName::common_name("testSubject")],
|
||||
generated,
|
||||
extensions,
|
||||
);
|
||||
|
||||
assert!(cert_result.is_ok());
|
||||
|
||||
Reference in New Issue
Block a user