/// <summary> /// Imports a collection of RFC 7468 PEM-encoded certificates. /// </summary> /// <param name="certPem">The text of the PEM-encoded X509 certificate collection.</param> /// <remarks> /// <para> /// PEM-encoded items with a CERTIFICATE PEM label will be imported. PEM items /// with other labels will be ignored. /// </para> /// <para> /// More advanced scenarios for loading certificates and /// can leverage <see cref="System.Security.Cryptography.PemEncoding" /> to enumerate /// PEM-encoded values and apply any custom loading behavior. /// </para> /// </remarks> /// <exception cref="CryptographicException"> /// The decoded contents of a PEM are invalid or corrupt and could not be imported. /// </exception> public void ImportFromPem(ReadOnlySpan <char> certPem) { int added = 0; try { foreach ((ReadOnlySpan <char> contents, PemFields fields) in new PemEnumerator(certPem)) { ReadOnlySpan <char> label = contents[fields.Label]; if (label.SequenceEqual(PemLabels.X509Certificate)) { // We verify below that every byte is written to. byte[] certBytes = GC.AllocateUninitializedArray <byte>(fields.DecodedDataLength); if (!Convert.TryFromBase64Chars(contents[fields.Base64Data], certBytes, out int bytesWritten) || bytesWritten != fields.DecodedDataLength) { Debug.Fail("The contents should have already been validated by the PEM reader."); throw new CryptographicException(SR.Cryptography_X509_NoPemCertificate); } try { // Check that the contents are actually an X509 DER encoded // certificate, not something else that the constructor will // will otherwise be able to figure out. CertificateAsn.Decode(certBytes, AsnEncodingRules.DER); } catch (CryptographicException) { throw new CryptographicException(SR.Cryptography_X509_NoPemCertificate); } Import(certBytes); added++; } } } catch { for (int i = 0; i < added; i++) { RemoveAt(Count - 1); } throw; } }
internal CertificateData(byte[] rawData) { #if DEBUG try { #endif RawData = rawData; certificate = CertificateAsn.Decode(rawData, AsnEncodingRules.DER); certificate.TbsCertificate.ValidateVersion(); Issuer = new X500DistinguishedName(certificate.TbsCertificate.Issuer.ToArray()); Subject = new X500DistinguishedName(certificate.TbsCertificate.Subject.ToArray()); using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER)) { certificate.TbsCertificate.SubjectPublicKeyInfo.Encode(writer); SubjectPublicKeyInfo = writer.Encode(); } Extensions = new List <X509Extension>(); if (certificate.TbsCertificate.Extensions != null) { foreach (X509ExtensionAsn rawExtension in certificate.TbsCertificate.Extensions) { X509Extension extension = new X509Extension( rawExtension.ExtnId, rawExtension.ExtnValue.ToArray(), rawExtension.Critical); Extensions.Add(extension); } } #if DEBUG } catch (Exception e) { throw new CryptographicException( $"Error in reading certificate:{Environment.NewLine}{PemPrintCert(rawData)}", e); } #endif }
internal CertificateData(byte[] rawData) { #if DEBUG try { #endif RawData = rawData; certificate = CertificateAsn.Decode(rawData, AsnEncodingRules.DER); certificate.TbsCertificate.ValidateVersion(); Issuer = new X500DistinguishedName(certificate.TbsCertificate.Issuer.Span); Subject = new X500DistinguishedName(certificate.TbsCertificate.Subject.Span); IssuerName = Issuer.Name; SubjectName = Subject.Name; AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); certificate.TbsCertificate.SubjectPublicKeyInfo.Encode(writer); SubjectPublicKeyInfo = writer.Encode(); Extensions = new List <X509Extension>((certificate.TbsCertificate.Extensions?.Length).GetValueOrDefault()); if (certificate.TbsCertificate.Extensions != null) { foreach (X509ExtensionAsn rawExtension in certificate.TbsCertificate.Extensions) { X509Extension extension = new X509Extension( rawExtension.ExtnId, rawExtension.ExtnValue.Span, rawExtension.Critical); Extensions.Add(extension); } } #if DEBUG } catch (Exception e) { string pem = PemEncoding.WriteString(PemLabels.X509Certificate, rawData); throw new CryptographicException($"Error in reading certificate:{Environment.NewLine}{pem}", e); } #endif }