/// <summary> /// Create a PEM-encoded PKCS#10 CertificationRequest representing the current state /// of this object using the provided signature generator. /// </summary> /// <param name="signatureGenerator"> /// A <see cref="X509SignatureGenerator"/> with which to sign the request. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="signatureGenerator" /> is <see langword="null" />. /// </exception> /// <exception cref="InvalidOperationException"> /// <para> /// <see cref="OtherRequestAttributes"/> contains a <see langword="null" /> value. /// </para> /// <para>- or -</para> /// <para> /// <see cref="OtherRequestAttributes"/> contains an entry with a <see langword="null" /> /// <see cref="AsnEncodedData.Oid" /> value. /// </para> /// <para>- or -</para> /// <para> /// <see cref="OtherRequestAttributes"/> contains an entry representing the PKCS#9 /// Extension Request Attribute (1.2.840.113549.1.9.14). /// </para> /// <para>- or -</para> /// <para> /// <see cref="CertificateExtensions"/> contains a <see langword="null" /> value. /// </para> /// <para>- or -</para> /// <para> /// <see cref="CertificateExtensions"/> contains an entry with a <see langword="null" /> /// <see cref="AsnEncodedData.Oid" /> value. /// </para> /// <para>- or -</para> /// <para> /// This object was created with a constructor which did not accept a signing key. /// </para> /// </exception> /// <exception cref="CryptographicException"> /// A cryptographic error occurs while creating the signing request. /// </exception> /// <seealso cref="CreateSigningRequest(X509SignatureGenerator)"/> public string CreateSigningRequestPem(X509SignatureGenerator signatureGenerator) { ArgumentNullException.ThrowIfNull(signatureGenerator); byte[] der = CreateSigningRequest(signatureGenerator); return(PemEncoding.WriteString(PemLabels.Pkcs10CertificateRequest, der)); }
public static unsafe bool TryExportToPem <T>( T arg, string label, TryExportKeyAction <T> exporter, Span <char> destination, out int charsWritten) { int bufferSize = 4096; while (true) { byte[] buffer = CryptoPool.Rent(bufferSize); int bytesWritten = 0; bufferSize = buffer.Length; // Fixed to prevent GC moves. fixed(byte *bufferPtr = buffer) { try { if (exporter(arg, buffer, out bytesWritten)) { Span <byte> writtenSpan = new Span <byte>(buffer, 0, bytesWritten); return(PemEncoding.TryWrite(label, writtenSpan, destination, out charsWritten)); } } finally { CryptoPool.Return(buffer, bytesWritten); } bufferSize = checked (bufferSize * 2); } } }
public static void ImportEncryptedPem <TPass>( ReadOnlySpan <char> input, ReadOnlySpan <TPass> password, ImportEncryptedKeyAction <TPass> importAction) { bool foundEncryptedPem = false; PemFields foundFields = default; ReadOnlySpan <char> foundSlice = default; ReadOnlySpan <char> pem = input; while (PemEncoding.TryFind(pem, out PemFields fields)) { ReadOnlySpan <char> label = pem[fields.Label]; if (label.SequenceEqual(PemLabels.EncryptedPkcs8PrivateKey)) { if (foundEncryptedPem) { throw new ArgumentException(SR.Argument_PemImport_AmbiguousPem, nameof(input)); } foundEncryptedPem = true; foundFields = fields; foundSlice = pem; } Index offset = fields.Location.End; pem = pem[offset..];
protected override PemFields FindPem(ReadOnlySpan <char> input) { bool found = PemEncoding.TryFind(input, out PemFields fields); Assert.True(found, "Did not find PEM."); return(fields); }
public static string ExportPemEncodedPublicKey(this RSA rsa) { var keyBytes = rsa.ExportRSAPublicKey(); var pemChars = PemEncoding.Write(PemEncodingLabels.RsaPublicKey, keyBytes); return(new string(pemChars)); }
public static void Write_Simple() { string label = "HELLO"; byte[] content = new byte[] { 0x66, 0x6F, 0x6F }; char[] result = PemEncoding.Write(label, content); string pem = new string(result); Assert.Equal("-----BEGIN HELLO-----\nZm9v\n-----END HELLO-----", pem); }
private static FileInfo CreateBundleFile(string directoryPath, X509Certificate2 certificate) { FileInfo file = new(Path.Combine(directoryPath, FallbackCertificateBundleX509ChainFactory.FileName)); char[] pem = PemEncoding.Write("CERTIFICATE", certificate.RawData); File.WriteAllText(file.FullName, new string(pem)); return(file); }
public static V1Secret?AsSecret(this PairingRecord?pairingRecord) { if (pairingRecord == null) { return(null); } var secret = new V1Secret() { ApiVersion = V1Secret.KubeApiVersion, Kind = V1Secret.KubeKind, Type = TlsType, Metadata = new V1ObjectMeta(), Data = new Dictionary <string, byte[]>(), Immutable = true, }; secret.Data[TlsCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.HostCertificate.Export(X509ContentType.Cert))); secret.Data[TlsPrivateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "PRIVATE KEY", pairingRecord.HostPrivateKey.ExportPkcs8PrivateKey())); secret.Data[CaCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.RootCertificate.Export(X509ContentType.Cert))); secret.Data[CaPrivateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "PRIVATE KEY", pairingRecord.RootPrivateKey.ExportPkcs8PrivateKey())); secret.Data[DeviceCertificateKey] = Encoding.UTF8.GetBytes( PemEncoding.Write( "CERTIFICATE", pairingRecord.DeviceCertificate.Export(X509ContentType.Cert))); secret.Data[EscrowBagKey] = pairingRecord.EscrowBag; secret.Data[HostIdKey] = Encoding.UTF8.GetBytes(pairingRecord.HostId); secret.Data[SystemBuidKey] = Encoding.UTF8.GetBytes(pairingRecord.SystemBUID); secret.Data[WifiMacAddressKey] = pairingRecord.WiFiMacAddress == null ? null : Encoding.UTF8.GetBytes(pairingRecord.WiFiMacAddress); return(secret); }
public string ExportPkcs7Pem() { byte[]? pkcs7 = Export(X509ContentType.Pkcs7); if (pkcs7 is null) { throw new CryptographicException(SR.Cryptography_X509_ExportFailed); } return(PemEncoding.WriteString(PemLabels.Pkcs7Certificate, pkcs7)); }
public static void TryWrite_Simple() { char[] buffer = new char[1000]; string label = "HELLO"; byte[] content = new byte[] { 0x66, 0x6F, 0x6F }; Assert.True(PemEncoding.TryWrite(label, content, buffer, out int charsWritten)); string pem = new string(buffer, 0, charsWritten); Assert.Equal("-----BEGIN HELLO-----\nZm9v\n-----END HELLO-----", pem); }
public bool TryExportPkcs7Pem(Span <char> destination, out int charsWritten) { byte[]? pkcs7 = Export(X509ContentType.Pkcs7); if (pkcs7 is null) { throw new CryptographicException(SR.Cryptography_X509_ExportFailed); } return(PemEncoding.TryWrite(PemLabels.Pkcs7Certificate, pkcs7, destination, out charsWritten)); }
/// <summary> /// Exports the private key of the specified certificate using the new .net 6 method /// </summary> /// <param name="certificate"></param> /// <returns></returns> private static string ExportPrivateKeyPkcs1Pem(X509Certificate2 certificate) { RSA rsa = certificate.GetRSAPrivateKey(); Assert.NotNull(rsa); byte[] privateKeyBytes = rsa.ExportRSAPrivateKey(); char[] privateKeyPem = PemEncoding.Write("RSA PRIVATE KEY", privateKeyBytes); return(new string(privateKeyPem)); }
public string ExportPkcs7Pem() { byte[]? pkcs7 = Export(X509ContentType.Pkcs7); if (pkcs7 is null) { throw new CryptographicException(SR.Cryptography_X509_ExportFailed); } int encodedSize = PemEncoding.GetEncodedSize(PemLabels.Pkcs7Certificate.Length, pkcs7.Length); return(string.Create(encodedSize, pkcs7, static (destination, pkcs7) => {
public static string GeneratePEMWithPrivateKeyAsString(X509Certificate2 certificate) { var sb = new StringBuilder(); AsymmetricAlgorithm key = certificate.GetRSAPrivateKey(); byte[] privKeyBytes = key.ExportPkcs8PrivateKey(); char[] privKeyPem = PemEncoding.Write("PRIVATE KEY", privKeyBytes); char[] certificatePem = PemEncoding.Write("CERTIFICATE", certificate.GetRawCertData()); sb.AppendLine(new string(privKeyPem)); sb.AppendLine(); sb.AppendLine(new string(certificatePem)); return(sb.ToString()); }
private static byte[] DecodePemData(ReadOnlySpan <char> pemData) { PemEncoding.TryFind(pemData, out PemFields fields); byte[] decodedData = new byte[fields.DecodedDataLength]; if (!Convert.TryFromBase64Chars(pemData[fields.Base64Data], decodedData, out _)) { throw new Exception("Error decoding pem data"); } return(decodedData); }
public X509Certificate2 GetValidationCert(TransportCustomizations settings) { try { var fields = PemEncoding.Find(settings.TLSValidationCert); var base64Data = settings.TLSValidationCert[fields.Base64Data]; return(new X509Certificate2(Encoding.ASCII.GetBytes(base64Data))); } catch (Exception e) { throw new HttpException(HttpStatusCode.BadRequest, $"Unable to instantiate a valid cert from the value provided in Transport settings key \"TLSValidationCert\". Value: \"{settings.TLSValidationCert}\". Message: \"{e.Message}\"."); } }
/// <summary> /// Attempts to export the public X.509 certificates, encoded as PEM. /// </summary> /// <param name="destination">The buffer to receive the PEM encoded certificates.</param> /// <param name="charsWritten">When this method returns, the total number of characters written to <paramref name="destination" />.</param> /// <returns> /// <see langword="true"/> if <paramref name="destination"/> was large enough to receive the encoded PEMs; /// otherwise, <see langword="false" />. /// </returns> /// <exception cref="CryptographicException"> /// A certificate is corrupt, in an invalid state, or could not be exported /// to PEM. /// </exception> /// <remarks> /// <p> /// A PEM-encoded X.509 certificate collection will contain certificates /// where each certificate begins with <c>-----BEGIN CERTIFICATE-----</c> /// and ends with <c>-----END CERTIFICATE-----</c>, with the base64 encoded DER /// contents of the certificate between the PEM boundaries. Each certificate is /// separated by a single line-feed character. /// </p> /// <p> /// Certificates are encoded according to the IETF RFC 7468 "strict" /// encoding rules. /// </p> /// </remarks> public bool TryExportCertificatePems(Span <char> destination, out int charsWritten) { Span <char> buffer = destination; int written = 0; for (int i = 0; i < Count; i++) { ReadOnlyMemory <byte> certData = this[i].RawDataMemory; int certSize = PemEncoding.GetEncodedSize(PemLabels.X509Certificate.Length, certData.Length); // If we ran out of space in the destination, return false. It's okay // that we may have successfully written data to the destination // already. Since certificates only contain "public" information, // we don't need to clear what has been written already. if (buffer.Length < certSize) { charsWritten = 0; return(false); } if (!PemEncoding.TryWrite(PemLabels.X509Certificate, certData.Span, buffer, out int certWritten) || certWritten != certSize) { Debug.Fail("Presized buffer is too small or did not write the correct amount."); throw new CryptographicException(); } buffer = buffer.Slice(certWritten); written += certWritten; // write a new line if not the last certificate. if (i < Count - 1) { if (buffer.IsEmpty) { charsWritten = 0; return(false); } // Always use Unix line endings between certificates to match the // behavior of PemEncoding.TryWrite, which is following RFC 7468. buffer[0] = '\n'; buffer = buffer.Slice(1); written++; } } charsWritten = written; return(true); }
internal static string CreatePemFromData(string label, ReadOnlyMemory <byte> data) { int pemSize = PemEncoding.GetEncodedSize(label.Length, data.Length); return(string.Create(pemSize, (label, data), static (destination, args) => { (string label, ReadOnlyMemory <byte> data) = args; if (!PemEncoding.TryWrite(label, data.Span, destination, out int charsWritten) || charsWritten != destination.Length) { Debug.Fail("Pre-allocated buffer was not the correct size."); throw new CryptographicException(); } }));
private string ToPEMCertificateChain(byte[] orderCertificate) { var certificateCollection = new X509Certificate2Collection(); certificateCollection.Import(orderCertificate); var stringBuilder = new StringBuilder(); foreach (var certificate in certificateCollection) { var certPem = PemEncoding.Write("CERTIFICATE", certificate.Export(X509ContentType.Cert)); stringBuilder.AppendLine(new string(certPem)); } return(stringBuilder.ToString()); }
private int GetCertificatePemsSize() { checked { int size = 0; for (int i = 0; i < Count; i++) { size += PemEncoding.GetEncodedSize(PemLabels.X509Certificate.Length, this[i].RawDataMemory.Length); // Add a \n character between each certificate, except the last one. if (i < Count - 1) { size += 1; } } return(size); } }
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 }
private static byte[] SerializeCertificate(X509Certificate certificate) { if (certificate == null) { return(null); } char[] pemEncoded = PemEncoding.Write( "CERTIFICATE", certificate.Export(X509ContentType.Cert)); // Append a \n character at the end var length = Encoding.UTF8.GetByteCount(pemEncoded) + 1; var bytes = new byte[length]; Encoding.UTF8.GetBytes(pemEncoded, bytes); bytes[length - 1] = 0xA; return(bytes); }
private static byte[] SerializePrivateKey(RSA privateKey) { if (privateKey == null) { return(null); } var pemEncoded = PemEncoding.Write( "RSA PRIVATE KEY", privateKey.ExportRSAPrivateKey()); // Append a \n character at the end var length = Encoding.UTF8.GetByteCount(pemEncoded) + 1; var bytes = new byte[length]; Encoding.UTF8.GetBytes(pemEncoded, bytes); bytes[length - 1] = 0xA; return(bytes); }
private static void WriteCertificateBundle(FileInfo certificateBundle, X509Certificate2Collection certificates) { FileInfo file = new(Path.GetTempFileName()); try { using (StreamWriter writer = new(file.FullName)) { foreach (X509Certificate2 certificate in certificates) { char[] pem = PemEncoding.Write("CERTIFICATE", certificate.RawData); writer.WriteLine(pem); writer.WriteLine(); } } File.Copy(file.FullName, certificateBundle.FullName, overwrite: true); } finally { file.Delete(); } }
public static unsafe bool TryExportToEncryptedPem <T>( T arg, ReadOnlySpan <char> password, PbeParameters pbeParameters, TryExportEncryptedKeyAction <T> exporter, Span <char> destination, out int charsWritten) { int bufferSize = 4096; while (true) { byte[] buffer = CryptoPool.Rent(bufferSize); int bytesWritten = 0; bufferSize = buffer.Length; // Fixed to prevent GC moves. fixed(byte *bufferPtr = buffer) { try { if (exporter(arg, password, pbeParameters, buffer, out bytesWritten)) { Span <byte> writtenSpan = new Span <byte>(buffer, 0, bytesWritten); return(PemEncoding.TryWrite(PemLabels.EncryptedPkcs8PrivateKey, writtenSpan, destination, out charsWritten)); } } finally { CryptoPool.Return(buffer, bytesWritten); } bufferSize = checked (bufferSize * 2); } } }
/// <summary> /// Converts this <see cref="X509Certificate2"/> to a <see cref="V1Secret"/>. /// </summary> /// <param name="certificate"> /// A <see cref="X509Certificate2"/> which represents a TLS certificate. /// </param> /// <returns> /// The equivalent <see cref="V1Secret"/>. /// </returns> public static V1Secret AsSecret(this X509Certificate2 certificate) { var secret = new V1Secret() { ApiVersion = V1Secret.KubeApiVersion, Kind = V1Secret.KubeKind, Type = TlsType, Metadata = new V1ObjectMeta() { // Must conform to a DNS subdomain naming rules, so all lowercase ASCII. Name = certificate.Thumbprint.ToLowerInvariant(), Labels = new Dictionary <string, string>(), }, Data = new Dictionary <string, byte[]>(), Immutable = true, }; var certificateAsPem = PemEncoding.Write( "CERTIFICATE", certificate.Export(X509ContentType.Cert)); secret.Data[TlsCertificate] = Encoding.UTF8.GetBytes(certificateAsPem); if (certificate.PrivateKey != null) { var keyAsPem = PemEncoding.Write( "PRIVATE KEY", certificate.PrivateKey.ExportPkcs8PrivateKey()); secret.Data[TlsPrivateKey] = Encoding.UTF8.GetBytes(keyAsPem); } return(secret); }
protected override void AssertNoPemFound(ReadOnlySpan <char> input) { AssertExtensions.Throws <ArgumentException, char>("pemData", input, x => PemEncoding.Find(x)); }
protected override PemFields FindPem(ReadOnlySpan <char> input) => PemEncoding.Find(input);
protected override void AssertNoPemFound(ReadOnlySpan <char> input) { bool found = PemEncoding.TryFind(input, out _); Assert.False(found, "Found PEM when not expected"); }
internal void ExportCertificate(X509Certificate2 certificate, string path, bool includePrivateKey, string password, CertificateKeyExportFormat format) { Log.ExportCertificateStart(GetDescription(certificate), path, includePrivateKey); if (includePrivateKey && password == null) { Log.NoPasswordForCertificate(); } var targetDirectoryPath = Path.GetDirectoryName(path); if (targetDirectoryPath != "") { Log.CreateExportCertificateDirectory(targetDirectoryPath); Directory.CreateDirectory(targetDirectoryPath); } byte[] bytes; byte[] keyBytes; byte[] pemEnvelope = null; RSA key = null; try { if (includePrivateKey) { switch (format) { case CertificateKeyExportFormat.Pfx: bytes = certificate.Export(X509ContentType.Pkcs12, password); break; case CertificateKeyExportFormat.Pem: key = certificate.GetRSAPrivateKey(); char[] pem; if (password != null) { keyBytes = key.ExportEncryptedPkcs8PrivateKey(password, new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100000)); pem = PemEncoding.Write("ENCRYPTED PRIVATE KEY", keyBytes); pemEnvelope = Encoding.ASCII.GetBytes(pem); } else { // Export the key first to an encrypted PEM to avoid issues with System.Security.Cryptography.Cng indicating that the operation is not supported. // This is likely by design to avoid exporting the key by mistake. // To bypass it, we export the certificate to pem temporarily and then we import it and export it as unprotected PEM. keyBytes = key.ExportEncryptedPkcs8PrivateKey("", new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1)); pem = PemEncoding.Write("ENCRYPTED PRIVATE KEY", keyBytes); key.Dispose(); key = RSA.Create(); key.ImportFromEncryptedPem(pem, ""); Array.Clear(keyBytes, 0, keyBytes.Length); Array.Clear(pem, 0, pem.Length); keyBytes = key.ExportPkcs8PrivateKey(); pem = PemEncoding.Write("PRIVATE KEY", keyBytes); pemEnvelope = Encoding.ASCII.GetBytes(pem); } Array.Clear(keyBytes, 0, keyBytes.Length); Array.Clear(pem, 0, pem.Length); bytes = certificate.Export(X509ContentType.Cert); break; default: throw new InvalidOperationException("Unknown format."); } } else { bytes = certificate.Export(X509ContentType.Cert); } } catch (Exception e) { Log.ExportCertificateError(e.ToString()); throw; } finally { key?.Dispose(); } try { Log.WriteCertificateToDisk(path); File.WriteAllBytes(path, bytes); } catch (Exception ex) { Log.WriteCertificateToDiskError(ex.ToString()); throw; } finally { Array.Clear(bytes, 0, bytes.Length); } if (includePrivateKey && format == CertificateKeyExportFormat.Pem) { try { var keyPath = Path.ChangeExtension(path, ".key"); Log.WritePemKeyToDisk(keyPath); File.WriteAllBytes(keyPath, pemEnvelope); } catch (Exception ex) { Log.WritePemKeyToDiskError(ex.ToString()); throw; } finally { Array.Clear(pemEnvelope, 0, pemEnvelope.Length); } } }