#![forbid(unsafe_code)]
#![deny(missing_docs)]
extern crate yasna;
extern crate ring;
#[cfg(feature = "pem")]
extern crate pem;
extern crate chrono;
use yasna::Tag;
use yasna::models::ObjectIdentifier;
#[cfg(feature = "pem")]
use pem::Pem;
#[cfg(feature = "pem")]
use std::convert::TryInto;
use ring::digest;
use ring::signature::{EcdsaKeyPair, Ed25519KeyPair, RsaKeyPair};
use ring::rand::SystemRandom;
use ring::signature::KeyPair as RingKeyPair;
use ring::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters};
use yasna::DERWriter;
use yasna::models::GeneralizedTime;
use chrono::{DateTime, Timelike};
use chrono::{NaiveDate, Utc};
use std::collections::HashMap;
use std::fmt;
use std::convert::TryFrom;
use std::error::Error;
pub struct Certificate {
params :CertificateParams,
key_pair :KeyPair,
}
pub fn generate_simple_self_signed(subject_alt_names :impl Into<Vec<String>>) -> Result<Certificate, RcgenError> {
Certificate::from_params(CertificateParams::new(subject_alt_names))
}
const OID_PKCS_9_AT_EXTENSION_REQUEST :&[u64] = &[1, 2, 840, 113549, 1, 9, 14];
const OID_COUNTRY_NAME :&[u64] = &[2, 5, 4, 6];
const OID_ORG_NAME :&[u64] = &[2, 5, 4, 10];
const OID_COMMON_NAME :&[u64] = &[2, 5, 4, 3];
const OID_EC_PUBLIC_KEY :&[u64] = &[1, 2, 840, 10045, 2, 1];
const OID_EC_SECP_256_R1 :&[u64] = &[1, 2, 840, 10045, 3, 1, 7];
const OID_EC_SECP_384_R1 :&[u64] = &[1, 3, 132, 0, 34];
const OID_RSA_ENCRYPTION :&[u64] = &[1, 2, 840, 113549, 1, 1, 1];
const OID_SUBJECT_ALT_NAME :&[u64] = &[2, 5, 29, 17];
const OID_BASIC_CONSTRAINTS :&[u64] = &[2, 5, 29, 19];
const OID_SUBJECT_KEY_IDENTIFIER :&[u64] = &[2, 5, 29, 14];
const OID_PE_ACME :&[u64] = &[1, 3, 6, 1, 5, 5, 7, 1, 31];
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
#[allow(missing_docs)]
pub enum DnType {
CountryName,
OrganizationName,
CommonName,
CustomDnType(Vec<u64>),
#[doc(hidden)]
_Nonexhaustive,
}
impl DnType {
fn to_oid(&self) -> ObjectIdentifier {
let sl = match self {
DnType::CountryName => OID_COUNTRY_NAME,
DnType::OrganizationName => OID_ORG_NAME,
DnType::CommonName => OID_COMMON_NAME,
DnType::CustomDnType(ref oid) => oid.as_slice(),
DnType::_Nonexhaustive => unimplemented!(),
};
ObjectIdentifier::from_slice(sl)
}
#[cfg(feature = "x509-parser")]
pub fn from_oid(slice :&[u64]) -> Self {
match slice {
OID_COMMON_NAME => DnType::CommonName,
OID_ORG_NAME => DnType::OrganizationName,
OID_COUNTRY_NAME => DnType::CountryName,
oid => DnType::CustomDnType(oid.into())
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DistinguishedName {
entries :HashMap<DnType, String>,
order :Vec<DnType>,
}
impl DistinguishedName {
pub fn new() -> Self {
Self {
entries : HashMap::new(),
order : Vec::new(),
}
}
pub fn get(&self, ty :&DnType) -> Option<&str> {
self.entries.get(ty).map(|s| {
let s :&str = s;
s
})
}
pub fn push(&mut self, ty :DnType, s :impl Into<String>) {
if !self.entries.contains_key(&ty) {
self.order.push(ty.clone());
}
self.entries.insert(ty, s.into());
}
pub fn iter(&self) -> DistinguishedNameIterator<'_> {
DistinguishedNameIterator {
distinguished_name :self,
iter :self.order.iter()
}
}
}
pub struct DistinguishedNameIterator<'a> {
distinguished_name :&'a DistinguishedName,
iter :std::slice::Iter<'a, DnType>,
}
impl <'a> Iterator for DistinguishedNameIterator<'a> {
type Item = (&'a DnType, &'a str);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
.and_then(|ty| {
self.distinguished_name.entries.get(ty).map(|v| (ty, v.as_str()))
})
}
}
#[allow(missing_docs)]
pub struct CertificateParams {
pub alg :&'static SignatureAlgorithm,
pub not_before :DateTime<Utc>,
pub not_after :DateTime<Utc>,
pub serial_number :Option<u64>,
pub subject_alt_names :Vec<String>,
pub distinguished_name :DistinguishedName,
pub is_ca :IsCa,
pub custom_extensions :Vec<CustomExtension>,
pub key_pair :Option<KeyPair>,
_hidden :(),
}
impl Default for CertificateParams {
fn default() -> Self {
let not_before = date_time_ymd(1975, 01, 01);
let not_after = date_time_ymd(4096, 01, 01);
let mut distinguished_name = DistinguishedName::new();
distinguished_name.push(DnType::CommonName, "rcgen self signed cert");
CertificateParams {
alg : &PKCS_ECDSA_P256_SHA256,
not_before,
not_after,
serial_number : None,
subject_alt_names : Vec::new(),
distinguished_name,
is_ca : IsCa::SelfSignedOnly,
custom_extensions : Vec::new(),
key_pair : None,
_hidden :(),
}
}
}
impl CertificateParams {
#[cfg(all(feature = "pem", feature = "x509-parser"))]
pub fn from_ca_cert_pem(pem_str :&str, key_pair :KeyPair) -> Result<Self, RcgenError> {
let certificate = pem::parse(pem_str)
.or(Err(RcgenError::CouldNotParseCertificate))?;
Self::from_ca_cert_der(&certificate.contents, key_pair)
}
#[cfg(feature = "x509-parser")]
pub fn from_ca_cert_der(ca_cert :&[u8], key_pair :KeyPair) -> Result<Self, RcgenError> {
let (_remainder, x509) = x509_parser::parse_x509_der(ca_cert)
.or(Err(RcgenError::CouldNotParseCertificate))?;
let alg = SignatureAlgorithm::from_oid(x509.signature_algorithm.algorithm.iter().as_slice())?;
let mut dn = DistinguishedName::new();
for rdn in x509.tbs_certificate.subject.rdn_seq.iter() {
assert!(rdn.set.len() != 0, "x509-parser distinguished name set is empty");
let attr = if rdn.set.len() > 1 {
return Err(RcgenError::CouldNotParseCertificate);
} else {
&rdn.set.as_slice()[0]
};
let value = attr.attr_value.as_slice()
.or(Err(RcgenError::CouldNotParseCertificate))?;
let dn_type = DnType::from_oid(attr.attr_type.iter().as_slice());
let dn_value = String::from_utf8(value.into())
.or(Err(RcgenError::CouldNotParseCertificate))?;
dn.push(dn_type, dn_value);
}
Ok(
CertificateParams {
alg,
distinguished_name : dn,
key_pair : Some(key_pair),
.. Default::default()
}
)
}
}
pub enum IsCa {
SelfSignedOnly,
Ca(BasicConstraints),
}
pub enum BasicConstraints {
Unconstrained,
Constrained(u8),
}
impl CertificateParams {
pub fn new(subject_alt_names :impl Into<Vec<String>>) -> Self {
CertificateParams {
subject_alt_names : subject_alt_names.into(),
.. Default::default()
}
}
}
pub struct CustomExtension {
oid :Vec<u64>,
critical :bool,
content :Vec<u8>,
}
impl CustomExtension {
pub fn new_acme_identifier(sha_digest :&[u8]) -> Self {
assert_eq!(sha_digest.len(), 32, "wrong size of sha_digest");
let content = yasna::construct_der(|writer| {
writer.write_bytes(sha_digest);
});
Self {
oid : OID_PE_ACME.to_owned(),
critical : true,
content,
}
}
pub fn from_oid_content(oid :&[u64], content :Vec<u8>) -> Self {
Self {
oid : oid.to_owned(),
critical : false,
content,
}
}
pub fn set_criticality(&mut self, criticality :bool) {
self.critical = criticality;
}
}
pub fn date_time_ymd(year :i32, month :u32, day :u32) -> DateTime<Utc> {
let naive_dt = NaiveDate::from_ymd(year, month, day).and_hms_milli(0, 0, 0, 0);
DateTime::<Utc>::from_utc(naive_dt, Utc)
}
fn dt_to_generalized(dt :&DateTime<Utc>) -> Result<GeneralizedTime, RcgenError> {
let mut date_time = *dt;
let nanos = if date_time.nanosecond() >= 1_000_000 {
1_000_000
} else {
0
};
date_time = date_time.with_nanosecond(nanos).ok_or(RcgenError::Time)?;
Ok(GeneralizedTime::from_datetime::<Utc>(&date_time))
}
impl Certificate {
pub fn from_params(mut params :CertificateParams) -> Result<Self, RcgenError> {
let key_pair = if let Some(key_pair) = params.key_pair.take() {
if !key_pair.is_compatible(¶ms.alg) {
return Err(RcgenError::CertificateKeyPairMismatch);
}
key_pair
} else {
KeyPair::generate(¶ms.alg)?
};
Ok(Certificate {
params,
key_pair,
})
}
fn write_name(&self, writer :DERWriter, ca :&Certificate) {
writer.write_sequence(|writer| {
for (ty, content) in ca.params.distinguished_name.iter() {
writer.next().write_set(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ty.to_oid());
writer.next().write_utf8_string(content);
});
});
}
});
}
fn write_request(&self, writer :DERWriter) {
writer.write_sequence(|writer| {
writer.next().write_u8(0);
writer.next().write_sequence(|writer| {
for (ty, content) in self.params.distinguished_name.iter() {
writer.next().write_set(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ty.to_oid());
writer.next().write_utf8_string(content);
});
});
}
});
self.key_pair.serialize_public_key_der(writer.next());
writer.next().write_tagged(Tag::context(0), |writer| {
writer.write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(OID_PKCS_9_AT_EXTENSION_REQUEST);
writer.next().write_oid(&oid);
writer.next().write_set(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(OID_SUBJECT_ALT_NAME);
writer.next().write_oid(&oid);
let bytes = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
for san in self.params.subject_alt_names.iter() {
const TAG_DNS_NAME :u64 = 2;
writer.next().write_tagged_implicit(Tag::context(TAG_DNS_NAME), |writer| {
writer.write_utf8_string(san);
});
}
});
});
writer.next().write_bytes(&bytes);
});
});
});
});
});
});
}
fn write_cert(&self, writer :DERWriter, ca :&Certificate) -> Result<(), RcgenError> {
writer.write_sequence(|writer| {
writer.next().write_tagged(Tag::context(0), |writer| {
writer.write_u8(2);
});
let serial = self.params.serial_number.unwrap_or(42);
writer.next().write_u64(serial);
self.params.alg.write_alg_ident(writer.next());
self.write_name(writer.next(), ca);
writer.next().write_sequence(|writer| {
let nb_gt = dt_to_generalized(&self.params.not_before)?;
writer.next().write_generalized_time(&nb_gt);
let na_gt = dt_to_generalized(&self.params.not_after)?;
writer.next().write_generalized_time(&na_gt);
Ok::<(), RcgenError>(())
})?;
self.write_name(writer.next(), self);
self.key_pair.serialize_public_key_der(writer.next());
writer.next().write_tagged(Tag::context(3), |writer| {
writer.write_sequence(|writer| {
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(OID_SUBJECT_ALT_NAME);
writer.next().write_oid(&oid);
let bytes = yasna::construct_der(|writer| {
writer.write_sequence(|writer|{
for san in self.params.subject_alt_names.iter() {
const TAG_DNS_NAME :u64 = 2;
writer.next().write_tagged_implicit(Tag::context(TAG_DNS_NAME), |writer| {
writer.write_utf8_string(san);
});
}
});
});
writer.next().write_bytes(&bytes);
});
if let IsCa::Ca(ref constraint) = self.params.is_ca {
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(OID_SUBJECT_KEY_IDENTIFIER);
writer.next().write_oid(&oid);
let digest = digest::digest(&self.params.alg.digest_alg, self.key_pair.public_key_raw().as_ref());
writer.next().write_bytes(&digest.as_ref());
});
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(OID_BASIC_CONSTRAINTS);
writer.next().write_oid(&oid);
let bytes = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_bool(true);
if let BasicConstraints::Constrained(path_len_constraint) = constraint {
writer.next().write_u8(*path_len_constraint);
}
});
});
writer.next().write_bytes(&bytes);
});
}
for ext in &self.params.custom_extensions {
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(&ext.oid);
writer.next().write_oid(&oid);
if ext.critical {
writer.next().write_bool(true);
}
writer.next().write_bytes(&ext.content);
});
}
});
});
Ok(())
})
}
pub fn serialize_der(&self) -> Result<Vec<u8>, RcgenError> {
self.serialize_der_with_signer(&self)
}
pub fn serialize_der_with_signer(&self, ca :&Certificate) -> Result<Vec<u8>, RcgenError> {
yasna::try_construct_der(|writer| {
writer.write_sequence(|writer| {
let tbs_cert_list_serialized = yasna::try_construct_der(|writer| {
self.write_cert(writer, ca)?;
Ok::<(), RcgenError>(())
})?;
writer.next().write_der(&tbs_cert_list_serialized);
self.params.alg.write_alg_ident(writer.next());
ca.key_pair.sign(&tbs_cert_list_serialized, writer.next())?;
Ok(())
})
})
}
pub fn serialize_request_der(&self) -> Result<Vec<u8>, RcgenError> {
yasna::try_construct_der(|writer| {
writer.write_sequence(|writer| {
let cert_data = yasna::construct_der(|writer| {
self.write_request(writer);
});
writer.next().write_der(&cert_data);
self.params.alg.write_alg_ident(writer.next());
self.key_pair.sign(&cert_data, writer.next())?;
Ok(())
})
})
}
pub fn get_key_pair(&self) -> &KeyPair {
&self.key_pair
}
#[cfg(feature = "pem")]
pub fn serialize_pem(&self) -> Result<String, RcgenError> {
let p = Pem {
tag : "CERTIFICATE".to_string(),
contents : self.serialize_der()?,
};
Ok(pem::encode(&p))
}
#[cfg(feature = "pem")]
pub fn serialize_pem_with_signer(&self, ca :&Certificate) -> Result<String, RcgenError> {
let p = Pem {
tag : "CERTIFICATE".to_string(),
contents : self.serialize_der_with_signer(ca)?,
};
Ok(pem::encode(&p))
}
#[cfg(feature = "pem")]
pub fn serialize_request_pem(&self) -> Result<String, RcgenError> {
let p = Pem {
tag : "CERTIFICATE REQUEST".to_string(),
contents : self.serialize_request_der()?,
};
Ok(pem::encode(&p))
}
pub fn serialize_private_key_der(&self) -> Vec<u8> {
self.key_pair.serialize_der()
}
#[cfg(feature = "pem")]
pub fn serialize_private_key_pem(&self) -> String {
self.key_pair.serialize_pem()
}
}
enum SignAlgo {
EcDsa(&'static EcdsaSigningAlgorithm),
EdDsa(&'static EdDSAParameters),
Rsa(),
}
#[derive(Debug)]
enum KeyPairKind {
Ec(EcdsaKeyPair),
Ed(Ed25519KeyPair),
Rsa(RsaKeyPair),
}
#[derive(Debug)]
pub struct KeyPair {
kind :KeyPairKind,
alg :&'static SignatureAlgorithm,
serialized_der :Vec<u8>,
}
impl KeyPair {
#[cfg(feature = "pem")]
pub fn from_pem(pem_str :&str) -> Result<Self, RcgenError> {
let private_key = pem::parse(pem_str)?;
let private_key_der :&[_] = &private_key.contents;
Ok(private_key_der.try_into()?)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum RcgenError {
CouldNotParseCertificate,
CouldNotParseKeyPair,
KeyGenerationUnavailable,
UnsupportedSignatureAlgorithm,
RingUnspecified,
CertificateKeyPairMismatch,
Time,
#[cfg(feature = "pem")]
PemError(pem::PemError),
#[doc(hidden)]
_Nonexhaustive,
}
impl fmt::Display for RcgenError {
fn fmt(&self, f :&mut fmt::Formatter) -> fmt::Result {
use self::RcgenError::*;
match self {
CouldNotParseCertificate => write!(f, "Could not parse certificate")?,
CouldNotParseKeyPair => write!(f, "Could not parse key pair")?,
KeyGenerationUnavailable => write!(f, "There is no support for generating \
keys for the given algorithm")?,
UnsupportedSignatureAlgorithm => write!(f, "The requested signature algorithm \
is not supported")?,
RingUnspecified => write!(f, "Unspecified ring error")?,
CertificateKeyPairMismatch => write!(f, "The provided certificate's signature \
algorithm is incompatible with the given key pair")?,
Time => write!(f, "Time error")?,
#[cfg(feature = "pem")]
PemError(e) => write!(f, "PEM error: {}", e)?,
_Nonexhaustive => panic!("Nonexhaustive error variant ought not be constructed"),
};
Ok(())
}
}
impl Error for RcgenError {}
impl From<ring::error::Unspecified> for RcgenError {
fn from(_unspecified :ring::error::Unspecified) -> Self {
RcgenError::RingUnspecified
}
}
#[cfg(feature = "pem")]
impl From<pem::PemError> for RcgenError {
fn from(_pem_error :pem::PemError) -> Self {
RcgenError::RingUnspecified
}
}
impl TryFrom<&[u8]> for KeyPair {
type Error = RcgenError;
fn try_from(pkcs8 :&[u8]) -> Result<KeyPair, RcgenError> {
let pkcs8_vec = std::iter::FromIterator::from_iter(pkcs8.iter().cloned());
let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) = EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8) {
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) = EcdsaKeyPair::from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8) {
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
(KeyPairKind::Rsa(rsakp), &PKCS_RSA_SHA256)
} else {
return Err(RcgenError::CouldNotParseKeyPair);
};
Ok(KeyPair {
kind,
alg,
serialized_der : pkcs8_vec,
})
}
}
impl KeyPair {
pub fn generate(alg :&'static SignatureAlgorithm) -> Result<Self, RcgenError> {
let system_random = SystemRandom::new();
match alg.sign_alg {
SignAlgo::EcDsa(sign_alg) => {
let key_pair_doc = EcdsaKeyPair::generate_pkcs8(sign_alg, &system_random)?;
let key_pair_serialized = key_pair_doc.as_ref().to_vec();
let key_pair = EcdsaKeyPair::from_pkcs8(&sign_alg, &&key_pair_doc.as_ref()).unwrap();
Ok(KeyPair {
kind : KeyPairKind::Ec(key_pair),
alg,
serialized_der : key_pair_serialized,
})
},
SignAlgo::EdDsa(_sign_alg) => {
let key_pair_doc = Ed25519KeyPair::generate_pkcs8(&system_random)?;
let key_pair_serialized = key_pair_doc.as_ref().to_vec();
let key_pair = Ed25519KeyPair::from_pkcs8(&&key_pair_doc.as_ref()).unwrap();
Ok(KeyPair {
kind : KeyPairKind::Ed(key_pair),
alg,
serialized_der : key_pair_serialized,
})
},
SignAlgo::Rsa() => Err(RcgenError::KeyGenerationUnavailable),
}
}
fn serialize_public_key_der(&self, writer :DERWriter) {
writer.write_sequence(|writer| {
self.alg.write_oids_sign_alg(writer.next());
let pk = self.public_key_raw();
writer.next().write_bitvec_bytes(&pk, pk.len() * 8);
})
}
pub fn public_key_raw(&self) -> &[u8] {
match &self.kind {
KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
KeyPairKind::Rsa(kp) => kp.public_key().as_ref(),
}
}
pub fn is_compatible(&self, signature_algorithm :&SignatureAlgorithm) -> bool {
self.alg == signature_algorithm
}
pub fn compatible_algs(&self)
-> impl Iterator<Item=&'static SignatureAlgorithm> {
std::iter::once(self.alg)
}
fn sign(&self, msg :&[u8], writer :DERWriter) -> Result<(), RcgenError> {
match &self.kind {
KeyPairKind::Ec(kp) => {
let system_random = SystemRandom::new();
let signature = kp.sign(&system_random, msg)?;
let sig = &signature.as_ref();
writer.write_bitvec_bytes(&sig, &sig.len() * 8);
},
KeyPairKind::Ed(kp) => {
let signature = kp.sign(msg);
let sig = &signature.as_ref();
writer.write_bitvec_bytes(&sig, &sig.len() * 8);
},
KeyPairKind::Rsa(kp) => {
let system_random = SystemRandom::new();
let mut signature = vec![0; kp.public_modulus_len()];
kp.sign(&signature::RSA_PKCS1_SHA256, &system_random,
msg, &mut signature)?;
let sig = &signature.as_ref();
writer.write_bitvec_bytes(&sig, &sig.len() * 8);
},
}
Ok(())
}
pub fn public_key_der(&self) -> Vec<u8> {
yasna::construct_der(|writer| self.serialize_public_key_der(writer))
}
#[cfg(feature = "pem")]
pub fn public_key_pem(&self) -> String {
let p = Pem {
tag : "PUBLIC KEY".to_string(),
contents : self.public_key_der(),
};
pem::encode(&p)
}
pub fn serialize_der(&self) -> Vec<u8> {
self.serialized_der.clone()
}
#[cfg(feature = "pem")]
pub fn serialize_pem(&self) -> String {
let p = Pem {
tag : "PRIVATE KEY".to_string(),
contents : self.serialize_der(),
};
pem::encode(&p)
}
}
pub struct SignatureAlgorithm {
oids_sign_alg :&'static [&'static [u64]],
sign_alg :SignAlgo,
digest_alg :&'static ring::digest::Algorithm,
oid_components :&'static [u64],
write_null_params :bool,
}
impl fmt::Debug for SignatureAlgorithm {
fn fmt(&self, f :&mut fmt::Formatter) -> fmt::Result {
if self == &PKCS_RSA_SHA256 {
write!(f, "PKCS_RSA_SHA256")
} else if self == &PKCS_ECDSA_P256_SHA256 {
write!(f, "PKCS_ECDSA_P256_SHA256")
} else if self == &PKCS_ECDSA_P384_SHA384 {
write!(f, "PKCS_ECDSA_P384_SHA384")
} else if self == &PKCS_ED25519 {
write!(f, "PKCS_ED25519")
} else {
write!(f, "Unknown")
}
}
}
impl PartialEq for SignatureAlgorithm {
fn eq(&self, other :&Self) -> bool {
let self_iter = self.oids_sign_alg.iter().map(|s| s.iter()).flatten();
let othr_iter = other.oids_sign_alg.iter().map(|s| s.iter()).flatten();
for (s, o) in self_iter.zip(othr_iter) {
if s != o {
return false;
}
}
true
}
}
impl Eq for SignatureAlgorithm {}
impl SignatureAlgorithm {
#[cfg(feature = "x509-parser")]
fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> {
static ALGORITHMS :&[&SignatureAlgorithm] = &[
&PKCS_RSA_SHA256,
&PKCS_ECDSA_P256_SHA256,
&PKCS_ECDSA_P384_SHA384,
&PKCS_ED25519
];
ALGORITHMS.iter()
}
#[cfg(feature = "x509-parser")]
pub fn from_oid(oid :&[u64]) -> Result<&'static SignatureAlgorithm, RcgenError> {
for algo in Self::iter() {
if algo.oid_components == oid {
return Ok(algo);
}
}
Err(RcgenError::UnsupportedSignatureAlgorithm)
}
}
pub static PKCS_RSA_SHA256 :SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg :&[&OID_RSA_ENCRYPTION],
sign_alg :SignAlgo::Rsa(),
digest_alg :&digest::SHA256,
oid_components : &[1, 2, 840, 113549, 1, 1, 11],
write_null_params : true,
};
pub static PKCS_ECDSA_P256_SHA256 :SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg :&[&OID_EC_PUBLIC_KEY, &OID_EC_SECP_256_R1],
sign_alg :SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING),
digest_alg :&digest::SHA256,
oid_components : &[1, 2, 840, 10045, 4, 3, 2],
write_null_params : false,
};
pub static PKCS_ECDSA_P384_SHA384 :SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg :&[&OID_EC_PUBLIC_KEY, &OID_EC_SECP_384_R1],
sign_alg :SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING),
digest_alg :&digest::SHA384,
oid_components : &[1, 2, 840, 10045, 4, 3, 3],
write_null_params : false,
};
pub static PKCS_ED25519 :SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg :&[&[1, 3, 101, 112]],
sign_alg :SignAlgo::EdDsa(&signature::ED25519),
digest_alg :&digest::SHA512,
oid_components : &[1, 3, 101, 112],
write_null_params : false,
};
impl SignatureAlgorithm {
fn alg_ident_oid(&self) -> ObjectIdentifier {
ObjectIdentifier::from_slice(self.oid_components)
}
fn write_alg_ident(&self, writer :DERWriter) {
writer.write_sequence(|writer| {
writer.next().write_oid(&self.alg_ident_oid());
if self.write_null_params {
writer.next().write_null();
}
});
}
fn write_oids_sign_alg(&self, writer :DERWriter) {
writer.write_sequence(|writer| {
for oid in self.oids_sign_alg {
let oid = ObjectIdentifier::from_slice(oid);
writer.next().write_oid(&oid);
}
if self.write_null_params {
writer.next().write_null();
}
});
}
}