private static unsafe AsnWriter?RewritePkcs8ECPrivateKeyWithZeroPublicKey(ReadOnlySpan <byte> source) { fixed(byte *ptr = &MemoryMarshal.GetReference(source)) { using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length)) { PrivateKeyInfoAsn privateKeyInfo = PrivateKeyInfoAsn.Decode(manager.Memory, AsnEncodingRules.BER); AlgorithmIdentifierAsn privateAlgorithm = privateKeyInfo.PrivateKeyAlgorithm; if (privateAlgorithm.Algorithm.Value != Oids.EcPublicKey) { return(null); } ECPrivateKey privateKey = ECPrivateKey.Decode(privateKeyInfo.PrivateKey, AsnEncodingRules.BER); EccKeyFormatHelper.FromECPrivateKey(privateKey, privateAlgorithm, out ECParameters ecParameters); fixed(byte *pD = ecParameters.D) { try { if (!ecParameters.Curve.IsExplicit || ecParameters.Q.X != null || ecParameters.Q.Y != null) { return(null); } byte[] zero = new byte[ecParameters.D !.Length];
/// <summary> /// Attempts to export the current key in the X.509 SubjectPublicKeyInfo format. /// </summary> /// <param name="destination">The byte span to receive the X.509 SubjectPublicKeyInfo data.</param> /// <param name="bytesWritten"> /// When this method returns, contains a value that indicates the number of bytes written to <paramref name="destination" />. /// This parameter is treated as uninitialized. /// </param> /// <returns> /// <see langword="true"/> if <paramref name="destination"/> is big enough to receive the output; /// otherwise, <see langword="false"/>. /// </returns> /// <exception cref="NotSupportedException"> /// The member <see cref="ExportParameters" /> has not been overridden in a derived class. /// </exception> /// <exception cref="ObjectDisposedException">The object has already been disposed.</exception> /// <exception cref="CryptographicException">The key is invalid and could not be exported.</exception> public virtual bool TryExportSubjectPublicKeyInfo(Span <byte> destination, out int bytesWritten) { ECParameters ecParameters = ExportParameters(); AsnWriter writer = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(ecParameters); return(writer.TryEncode(destination, out bytesWritten)); }
internal unsafe int ImportSubjectPublicKeyInfo( ReadOnlySpan <byte> source, out int bytesRead) { ThrowIfDisposed(); fixed(byte *ptr = &MemoryMarshal.GetReference(source)) { using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length)) { // Validate the DER value and get the number of bytes. EccKeyFormatHelper.ReadSubjectPublicKeyInfo( manager.Memory, out int localRead); SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false); SecKeyPair newKeys = SecKeyPair.PublicOnly(publicKey); int size = GetKeySize(newKeys); SetKey(newKeys); bytesRead = localRead; return(size); } } }
/// <summary> /// Exports the current key in the X.509 SubjectPublicKeyInfo format. /// </summary> /// <returns> /// A byte array containing the X.509 SubjectPublicKeyInfo representation of this key. /// </returns> /// <exception cref="NotSupportedException"> /// The member <see cref="ExportParameters" /> has not been overridden in a derived class. /// </exception> /// <exception cref="ObjectDisposedException">The object has already been disposed.</exception> /// <exception cref="CryptographicException">The key is invalid and could not be exported.</exception> public virtual byte[] ExportSubjectPublicKeyInfo() { ECParameters ecParameters = ExportParameters(); AsnWriter writer = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(ecParameters); return(writer.Encode()); }
/// <summary> /// Attempts to export the current key in the PKCS#8 EncryptedPrivateKeyInfo /// format into a provided buffer, using a char-based password. /// </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> /// <param name="destination"> /// The byte span to receive the PKCS#8 EncryptedPrivateKeyInfo data. /// </param> /// <param name="bytesWritten"> /// When this method returns, contains a value that indicates the number /// of bytes written to <paramref name="destination" />. This parameter /// is treated as uninitialized. /// </param> /// <returns> /// <see langword="true" /> if <paramref name="destination" /> is big enough /// to receive the output; otherwise, <see langword="false" />. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="pbeParameters" /> is <see langword="null" />. /// </exception> /// <exception cref="NotSupportedException"> /// A derived class has not provided an implementation for <see cref="ExportParameters" />. /// </exception> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <remarks> /// 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. /// </remarks> public override unsafe bool TryExportEncryptedPkcs8PrivateKey( ReadOnlySpan <char> password, PbeParameters pbeParameters, Span <byte> destination, out int bytesWritten) { ArgumentNullException.ThrowIfNull(pbeParameters); PasswordBasedEncryption.ValidatePbeParameters( pbeParameters, password, ReadOnlySpan <byte> .Empty); ECParameters ecParameters = ExportParameters(true); fixed(byte *privPtr = ecParameters.D) { try { AsnWriter pkcs8PrivateKey = EccKeyFormatHelper.WritePkcs8PrivateKey(ecParameters); AsnWriter writer = KeyFormatHelper.WriteEncryptedPkcs8( password, pkcs8PrivateKey, pbeParameters); return(writer.TryEncode(destination, out bytesWritten)); } finally { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
private static void ExtractPublicKeyFromPrivateKey(ref ECParameters ecParameters) { using (SafeSecKeyRefHandle secPrivateKey = ImportLegacyPrivateKey(ref ecParameters)) { const string ExportPassword = "******"; byte[] keyBlob = Interop.AppleCrypto.SecKeyExport(secPrivateKey, exportPrivate: true, password: ExportPassword); EccKeyFormatHelper.ReadEncryptedPkcs8(keyBlob, ExportPassword, out _, out ecParameters); CryptographicOperations.ZeroMemory(keyBlob); } }
public override bool TryExportSubjectPublicKeyInfo( Span <byte> destination, out int bytesWritten) { ECParameters ecParameters = ExportParameters(false); using (AsnWriter writer = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(ecParameters)) { return(writer.TryEncode(destination, out bytesWritten)); } }
internal static ECParameters ExportPublicParametersFromPrivateKey(SafeSecKeyRefHandle handle) { const string ExportPassword = "******"; byte[] keyBlob = Interop.AppleCrypto.SecKeyExport(handle, exportPrivate: true, password: ExportPassword); EccKeyFormatHelper.ReadEncryptedPkcs8(keyBlob, ExportPassword, out _, out ECParameters key); CryptographicOperations.ZeroMemory(key.D); CryptographicOperations.ZeroMemory(keyBlob); key.D = null; return(key); }
private static SafeSecKeyRefHandle ImportKey(ECParameters parameters) { if (parameters.D != null) { using (AsnWriter privateKey = EccKeyFormatHelper.WriteECPrivateKey(parameters)) { return(Interop.AppleCrypto.ImportEphemeralKey(privateKey.EncodeAsSpan(), true)); } } else { using (AsnWriter publicKey = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters)) { return(Interop.AppleCrypto.ImportEphemeralKey(publicKey.EncodeAsSpan(), false)); } } }
/// <summary> /// Imports the public/private keypair from an ECPrivateKey structure, /// replacing the keys for this object. /// </summary> /// <param name="source">The bytes of an ECPrivateKey structure in the ASN.1-BER encoding.</param> /// <param name="bytesRead"> /// When this method returns, contains a value that indicates the number /// of bytes read from <paramref name="source" />. This parameter is treated as uninitialized. /// </param> /// <exception cref="NotSupportedException"> /// A derived class has not provided an implementation for <see cref="ImportParameters" />. /// </exception> /// <exception cref="CryptographicException"> /// <p> /// The contents of <paramref name="source" /> do not represent an /// ASN.1-BER-encoded PKCS#8 ECPrivateKey structure. /// </p> /// <p>-or-</p> /// <p>The key import failed.</p> /// </exception> /// <remarks> /// This method only supports the binary (BER/CER/DER) encoding of ECPrivateKey. /// If the value is Base64-encoded, the caller must Base64-decode the contents before calling this method. /// If the value is PEM-encoded, <see cref="ImportFromPem" /> should be used. /// </remarks> public virtual unsafe void ImportECPrivateKey(ReadOnlySpan <byte> source, out int bytesRead) { ECParameters ecParameters = EccKeyFormatHelper.FromECPrivateKey(source, out int localRead); fixed(byte *privPin = ecParameters.D) { try { ImportParameters(ecParameters); bytesRead = localRead; } finally { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
/// <summary>Exports the current key in the ECPrivateKey format.</summary> /// <returns>A byte array containing the ECPrivateKey representation of this key.</returns> /// <exception cref="CryptographicException">The key could not be exported.</exception> public virtual unsafe byte[] ExportECPrivateKey() { ECParameters ecParameters = ExportParameters(true); fixed(byte *privPin = ecParameters.D) { try { AsnWriter writer = EccKeyFormatHelper.WriteECPrivateKey(ecParameters); return(writer.Encode()); } finally { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
/// <summary> /// Attempts to export the current key in the ECPrivateKey format into a provided buffer. /// </summary> /// <param name="destination">The byte span to receive the ECPrivateKey data.</param> /// <param name="bytesWritten">When this method returns, contains a value /// that indicates the number of bytes written to <paramref name="destination" />. /// This parameter is treated as uninitialized. /// </param> /// <returns> /// <see langword="true" /> if <paramref name="destination" /> is big enough /// to receive the output; otherwise, <see langword="false" />. /// </returns> /// <exception cref="CryptographicException"> /// The key could not be exported. /// </exception> /// <exception cref="NotSupportedException"> /// A derived class has not provided an implementation for <see cref="ExportParameters" />. /// </exception> public virtual unsafe bool TryExportECPrivateKey(Span <byte> destination, out int bytesWritten) { ECParameters ecParameters = ExportParameters(true); fixed(byte *privPin = ecParameters.D) { try { AsnWriter writer = EccKeyFormatHelper.WriteECPrivateKey(ecParameters); return(writer.TryEncode(destination, out bytesWritten)); } finally { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
internal ECParameters ExportParameters(bool includePrivateParameters, int keySizeInBits) { // Apple requires all private keys to be exported encrypted, but since we're trying to export // as parsed structures we will need to decrypt it for the user. const string ExportPassword = "******"; SecKeyPair keys = GetOrGenerateKeys(keySizeInBits); if (keys.PublicKey == null || (includePrivateParameters && keys.PrivateKey == null)) { throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); } byte[] keyBlob = Interop.AppleCrypto.SecKeyExport( includePrivateParameters ? keys.PrivateKey : keys.PublicKey, exportPrivate: includePrivateParameters, password: ExportPassword); try { if (!includePrivateParameters) { EccKeyFormatHelper.ReadSubjectPublicKeyInfo( keyBlob, out int localRead, out ECParameters key); return(key); } else { EccKeyFormatHelper.ReadEncryptedPkcs8( keyBlob, ExportPassword, out int localRead, out ECParameters key); return(key); } } finally { CryptographicOperations.ZeroMemory(keyBlob); } }
public override unsafe bool TryExportPkcs8PrivateKey( Span <byte> destination, out int bytesWritten) { ECParameters ecParameters = ExportParameters(true); fixed(byte *privPtr = ecParameters.D) { try { using (AsnWriter writer = EccKeyFormatHelper.WritePkcs8PrivateKey(ecParameters)) { return(writer.TryEncode(destination, out bytesWritten)); } } finally { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
private static SafeSecKeyRefHandle ImportKey(ECParameters parameters) { bool isPrivateKey = parameters.D != null; byte[] blob; if (isPrivateKey) { using (AsnWriter privateKey = EccKeyFormatHelper.WriteECPrivateKey(parameters)) { blob = privateKey.Encode(); } } else { using (AsnWriter publicKey = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters)) { blob = publicKey.Encode(); } } return(Interop.AppleCrypto.ImportEphemeralKey(blob, isPrivateKey)); }
private static SafeSecKeyRefHandle ImportKey(ECParameters parameters) { AsnWriter keyWriter; bool hasPrivateKey; if (parameters.D != null) { keyWriter = EccKeyFormatHelper.WriteECPrivateKey(parameters); hasPrivateKey = true; } else { keyWriter = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters); hasPrivateKey = false; } byte[] rented = CryptoPool.Rent(keyWriter.GetEncodedLength()); if (!keyWriter.TryEncode(rented, out int written)) { Debug.Fail("TryEncode failed with a pre-allocated buffer"); throw new InvalidOperationException(); } // Explicitly clear the inner buffer keyWriter.Reset(); try { return(Interop.AppleCrypto.ImportEphemeralKey(rented.AsSpan(0, written), hasPrivateKey)); } finally { CryptoPool.Return(rented, written); } }
private static SafeSecKeyRefHandle ImportLegacyPrivateKey(ref ECParameters parameters) { AsnWriter keyWriter = EccKeyFormatHelper.WriteECPrivateKey(parameters); byte[] rented = CryptoPool.Rent(keyWriter.GetEncodedLength()); if (!keyWriter.TryEncode(rented, out int written)) { Debug.Fail("TryEncode failed with a pre-allocated buffer"); throw new InvalidOperationException(); } // Explicitly clear the inner buffer keyWriter.Reset(); try { return(Interop.AppleCrypto.ImportEphemeralKey(rented.AsSpan(0, written), true)); } finally { CryptoPool.Return(rented, written); } }
private static ECParameters ExportParametersFromLegacyKey(SecKeyPair keys, bool includePrivateParameters) { // Apple requires all private keys to be exported encrypted, but since we're trying to export // as parsed structures we will need to decrypt it for the user. const string ExportPassword = "******"; byte[] keyBlob = Interop.AppleCrypto.SecKeyExport( includePrivateParameters ? keys.PrivateKey : keys.PublicKey, exportPrivate: includePrivateParameters, password: ExportPassword); try { if (!includePrivateParameters) { EccKeyFormatHelper.ReadSubjectPublicKeyInfo( keyBlob, out int localRead, out ECParameters key); return(key); } else { EccKeyFormatHelper.ReadEncryptedPkcs8( keyBlob, ExportPassword, out int localRead, out ECParameters key); return(key); } } finally { CryptographicOperations.ZeroMemory(keyBlob); } }