/// <summary> /// Imports an RFC 7468 PEM-encoded key, replacing the keys for this object. /// </summary> /// <param name="input">The PEM text of the key to import.</param> /// <exception cref="ArgumentException"> /// <para> /// <paramref name="input"/> does not contain a PEM-encoded key with a recognized label. /// </para> /// <para> /// -or- /// </para> /// <para> /// <paramref name="input"/> contains multiple PEM-encoded keys with a recognized label. /// </para> /// <para> /// -or- /// </para> /// <para> /// <paramref name="input"/> contains an encrypted PEM-encoded key. /// </para> /// </exception> /// <remarks> /// <para> /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels /// are found, an exception is raised to prevent importing a key when /// the key is ambiguous. /// </para> /// <para> /// This method supports the following PEM labels: /// <list type="bullet"> /// <item><description>PUBLIC KEY</description></item> /// <item><description>PRIVATE KEY</description></item> /// <item><description>RSA PRIVATE KEY</description></item> /// <item><description>RSA PUBLIC KEY</description></item> /// </list> /// </para> /// </remarks> public override void ImportFromPem(ReadOnlySpan <char> input) { PemKeyHelpers.ImportPem(input, label => { if (label.SequenceEqual(PemLabels.RsaPrivateKey)) { return(ImportRSAPrivateKey); } else if (label.SequenceEqual(PemLabels.Pkcs8PrivateKey)) { return(ImportPkcs8PrivateKey); } else if (label.SequenceEqual(PemLabels.RsaPublicKey)) { return(ImportRSAPublicKey); } else if (label.SequenceEqual(PemLabels.SpkiPublicKey)) { return(ImportSubjectPublicKeyInfo); } else { return(null); } }); }
/// <summary> /// Imports an RFC 7468 textually encoded key, replacing the keys for this object. /// </summary> /// <param name="input">The text of the PEM key to import.</param> /// <exception cref="ArgumentException"> /// <para> /// <paramref name="input"/> does not contain a PEM-encoded key with a recognized label. /// </para> /// <para> /// -or- /// </para> /// <para> /// <paramref name="input"/> contains multiple PEM-encoded keys with a recognized label. /// </para> /// <para> /// -or- /// </para> /// <para> /// <paramref name="input"/> contains an encrypted PEM-encoded key. /// </para> /// </exception> /// <exception cref="NotImplementedException"> /// A derived type has not provided an implementation for <see cref="ImportPkcs8PrivateKey" /> /// or <see cref="ImportSubjectPublicKeyInfo" />. /// </exception> /// <remarks> /// <para> /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels /// are found, an exception is raised to prevent importing a key when /// the key is ambiguous. /// </para> /// <para> /// This method supports the following PEM labels: /// <list type="bullet"> /// <item><description>PUBLIC KEY</description></item> /// <item><description>PRIVATE KEY</description></item> /// </list> /// </para> /// <para> /// Types that override this method may support additional PEM labels. /// </para> /// </remarks> public virtual void ImportFromPem(ReadOnlySpan <char> input) { PemKeyHelpers.ImportPem(input, label => label switch { PemLabels.Pkcs8PrivateKey => ImportPkcs8PrivateKey, PemLabels.SpkiPublicKey => ImportSubjectPublicKeyInfo, _ => null, });
/// <summary> /// Exports the current key in the PKCS#1 RSAPrivateKey format, PEM encoded. /// </summary> /// <returns>A string containing the PEM-encoded PKCS#1 RSAPrivateKey.</returns> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <remarks> /// <p> /// A PEM-encoded PKCS#1 RSAPrivateKey will begin with <c>-----BEGIN RSA PRIVATE KEY-----</c> /// and end with <c>-----END RSA PRIVATE KEY-----</c>, with the base64 encoded DER /// contents of the key between the PEM boundaries. /// </p> /// <p> /// The PEM is encoded according to the IETF RFC 7468 "strict" /// encoding rules. /// </p> /// </remarks> public unsafe string ExportRSAPrivateKeyPem() { byte[] exported = ExportRSAPrivateKey(); // Fixed to prevent GC moves. fixed(byte *pExported = exported) { try { return(PemKeyHelpers.CreatePemFromData(PemLabels.RsaPrivateKey, exported)); } finally { CryptographicOperations.ZeroMemory(exported); } } }
/// <summary> /// Exports the current key in the PKCS#8 EncryptedPrivateKeyInfo format /// with a char-based password, PEM encoded. /// </summary> /// <param name="password"> /// The password to use when encrypting the key material. /// </param> /// <param name="pbeParameters"> /// The password-based encryption (PBE) parameters to use when encrypting the key material. /// </param> /// <returns>A string containing the PEM-encoded PKCS#8 EncryptedPrivateKeyInfo.</returns> /// <exception cref="NotImplementedException"> /// An implementation for <see cref="ExportEncryptedPkcs8PrivateKey(ReadOnlySpan{char}, PbeParameters)" /> or /// <see cref="TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan{char}, PbeParameters, Span{byte}, out int)" /> has not been provided. /// </exception> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <remarks> /// <p> /// When <paramref name="pbeParameters" /> indicates an algorithm that /// uses PBKDF2 (Password-Based Key Derivation Function 2), the password /// is converted to bytes via the UTF-8 encoding. /// </p> /// <p> /// A PEM-encoded PKCS#8 EncryptedPrivateKeyInfo will begin with /// <c>-----BEGIN ENCRYPTED PRIVATE KEY-----</c> and end with /// <c>-----END ENCRYPTED PRIVATE KEY-----</c>, with the base64 encoded DER /// contents of the key between the PEM boundaries. /// </p> /// <p> /// The PEM is encoded according to the IETF RFC 7468 "strict" /// encoding rules. /// </p> /// </remarks> public unsafe string ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan <char> password, PbeParameters pbeParameters) { byte[] exported = ExportEncryptedPkcs8PrivateKey(password, pbeParameters); // Fixed to prevent GC moves. fixed(byte *pExported = exported) { try { return(PemKeyHelpers.CreatePemFromData(PemLabels.EncryptedPkcs8PrivateKey, exported)); } finally { CryptographicOperations.ZeroMemory(exported); } } }
/// <summary> /// Imports an encrypted RFC 7468 PEM-encoded key, replacing the keys for this object. /// </summary> /// <param name="input">The PEM text of the encrypted key to import.</param> /// <param name="passwordBytes"> /// The bytes to use as a password when decrypting the key material. /// </param> /// <exception cref="ArgumentException"> /// <para> /// <paramref name="input"/> does not contain a PEM-encoded key with a recognized label. /// </para> /// <para> /// -or- /// </para> /// <para> /// <paramref name="input"/> contains multiple PEM-encoded keys with a recognized label. /// </para> /// </exception> /// <exception cref="CryptographicException"> /// <para> /// The password is incorrect. /// </para> /// <para> /// -or- /// </para> /// <para> /// The base-64 decoded contents of the PEM text from <paramref name="input" /> /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. /// </para> /// <para> /// -or- /// </para> /// <para> /// The base-64 decoded contents of the PEM text from <paramref name="input" /> /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. /// </para> /// <para> /// -or- /// </para> /// <para> /// The base-64 decoded contents of the PEM text from <paramref name="input" /> /// represent the key in a format that is not supported. /// </para> /// <para> /// -or- /// </para> /// <para> /// The algorithm-specific key import failed. /// </para> /// </exception> /// <exception cref="NotImplementedException"> /// A derived type has not provided an implementation for /// <see cref="ImportEncryptedPkcs8PrivateKey(ReadOnlySpan{byte}, ReadOnlySpan{byte}, out int)" />. /// </exception> /// <remarks> /// <para> /// The password bytes are passed directly into the Key Derivation Function (KDF) /// used by the algorithm indicated by <c>pbeParameters</c>. This enables compatibility /// with other systems which use a text encoding other than UTF-8 when processing /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). /// </para> /// <para> /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// </para> /// <para>This method supports the <c>ENCRYPTED PRIVATE KEY</c> PEM label.</para> /// <para> /// Types that override this method may support additional PEM labels. /// </para> /// </remarks> public virtual void ImportFromEncryptedPem(ReadOnlySpan <char> input, ReadOnlySpan <byte> passwordBytes) { PemKeyHelpers.ImportEncryptedPem <byte>(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); }
/// <summary> /// Exports the public-key portion of the current key in the PKCS#1 /// RSAPublicKey format, PEM encoded. /// </summary> /// <returns>A string containing the PEM-encoded PKCS#1 RSAPublicKey.</returns> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <remarks> /// <p> /// A PEM-encoded PKCS#1 RSAPublicKey will begin with <c>-----BEGIN RSA PUBLIC KEY-----</c> /// and end with <c>-----END RSA PUBLIC KEY-----</c>, with the base64 encoded DER /// contents of the key between the PEM boundaries. /// </p> /// <p> /// The PEM is encoded according to the IETF RFC 7468 "strict" /// encoding rules. /// </p> /// </remarks> public string ExportRSAPublicKeyPem() { byte[] exported = ExportRSAPublicKey(); return(PemKeyHelpers.CreatePemFromData(PemLabels.RsaPublicKey, exported)); }
/// <summary> /// Exports the public-key portion of the current key in the X.509 /// SubjectPublicKeyInfo format, PEM encoded. /// </summary> /// <returns>A string containing the PEM-encoded X.509 SubjectPublicKeyInfo.</returns> /// <exception cref="NotImplementedException"> /// An implementation for <see cref="ExportSubjectPublicKeyInfo" /> or /// <see cref="TryExportSubjectPublicKeyInfo" /> has not been provided. /// </exception> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <remarks> /// <p> /// A PEM-encoded X.509 SubjectPublicKeyInfo will begin with /// <c>-----BEGIN PUBLIC KEY-----</c> and end with /// <c>-----END PUBLIC KEY-----</c>, with the base64 encoded DER /// contents of the key between the PEM boundaries. /// </p> /// <p> /// The PEM is encoded according to the IETF RFC 7468 "strict" /// encoding rules. /// </p> /// </remarks> public string ExportSubjectPublicKeyInfoPem() { byte[] exported = ExportSubjectPublicKeyInfo(); return(PemKeyHelpers.CreatePemFromData(PemLabels.SpkiPublicKey, exported)); }