Beispiel #1
0
 internal static void ReadEncryptedPkcs8(
     ReadOnlySpan <byte> source,
     ReadOnlySpan <byte> passwordBytes,
     out int bytesRead,
     out ECParameters key)
 {
     KeyFormatHelper.ReadEncryptedPkcs8 <ECParameters>(
         s_validOids,
         source,
         passwordBytes,
         FromECPrivateKey,
         out bytesRead,
         out key);
 }
Beispiel #2
0
        public override void ImportSubjectPublicKeyInfo(
            ReadOnlySpan <byte> source,
            out int bytesRead)
        {
            KeyFormatHelper.ReadSubjectPublicKeyInfo <ECParameters>(
                s_validOids,
                source,
                EccKeyFormatHelper.FromECPublicKey,
                out int localRead,
                out ECParameters key);

            ImportParameters(key);
            bytesRead = localRead;
        }
Beispiel #3
0
        internal static unsafe Pkcs8Response ImportEncryptedPkcs8PrivateKey(
            ReadOnlySpan <byte> passwordBytes,
            ReadOnlySpan <byte> source,
            out int bytesRead)
        {
            fixed(byte *ptr = &MemoryMarshal.GetReference(source))
            {
                using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length))
                {
                    // Since there's no bytes-based-password PKCS8 import in CNG, just do the decryption
                    // here and call the unencrypted PKCS8 import.
                    ArraySegment <byte> decrypted = KeyFormatHelper.DecryptPkcs8(
                        passwordBytes,
                        manager.Memory,
                        out bytesRead);

                    Span <byte> decryptedSpan = decrypted;

                    try
                    {
                        return(ImportPkcs8(decryptedSpan));
                    }
                    catch (CryptographicException e)
                    {
                        AsnWriter?pkcs8ZeroPublicKey = RewritePkcs8ECPrivateKeyWithZeroPublicKey(decryptedSpan);

                        if (pkcs8ZeroPublicKey == null)
                        {
                            throw new CryptographicException(SR.Cryptography_Pkcs8_EncryptedReadFailed, e);
                        }

                        try
                        {
                            return(ImportPkcs8(pkcs8ZeroPublicKey.EncodeAsSpan()));
                        }
                        catch (CryptographicException)
                        {
                            throw new CryptographicException(SR.Cryptography_Pkcs8_EncryptedReadFailed, e);
                        }
                    }
                    finally
                    {
                        CryptographicOperations.ZeroMemory(decryptedSpan);
                        CryptoPool.Return(decrypted.Array !);
                    }
                }
            }
        }
Beispiel #4
0
        public override unsafe void ImportPkcs8PrivateKey(ReadOnlySpan <byte> source, out int bytesRead)
        {
            fixed(byte *ptr = &MemoryMarshal.GetReference(source))
            {
                using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length))
                {
                    ReadOnlyMemory <byte> pkcs1 = KeyFormatHelper.ReadPkcs8(
                        s_validOids,
                        manager.Memory,
                        out int localRead);

                    ImportRSAPrivateKey(pkcs1.Span, out _);
                    bytesRead = localRead;
                }
            }
        }
Beispiel #5
0
        public override bool TryExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan <byte> passwordBytes,
            PbeParameters pbeParameters,
            Span <byte> destination,
            out int bytesWritten)
        {
            ArgumentNullException.ThrowIfNull(pbeParameters);

            PasswordBasedEncryption.ValidatePbeParameters(
                pbeParameters,
                ReadOnlySpan <char> .Empty,
                passwordBytes);

            AsnWriter pkcs8PrivateKey = WritePkcs8PrivateKey();

            AsnWriter writer = KeyFormatHelper.WriteEncryptedPkcs8(
                passwordBytes,
                pkcs8PrivateKey,
                pbeParameters);

            return(writer.TryEncode(destination, out bytesWritten));
        }
        public override unsafe bool TryExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan <char> password,
            PbeParameters pbeParameters,
            Span <byte> destination,
            out int bytesWritten)
        {
            if (pbeParameters == null)
            {
                throw new ArgumentNullException(nameof(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);
                }
            }
        }
Beispiel #7
0
        private static AsnWriter RewriteEncryptedPkcs8PrivateKey(
            AsymmetricAlgorithm key,
            ReadOnlySpan <char> password,
            PbeParameters pbeParameters)
        {
            Debug.Assert(pbeParameters != null);

            byte[] rented = ArrayPool <byte> .Shared.Rent(key.KeySize);

            int rentWritten = 0;

            try
            {
                while (!key.TryExportEncryptedPkcs8PrivateKey(
                           password,
                           s_platformParameters,
                           rented,
                           out rentWritten))
                {
                    int size = rented.Length;
                    ArrayPool <byte> .Shared.Return(rented);

                    rented = ArrayPool <byte> .Shared.Rent(checked (size * 2));
                }

                return(KeyFormatHelper.ReencryptPkcs8(
                           password,
                           rented.AsMemory(0, rentWritten),
                           password,
                           pbeParameters));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(rented.AsSpan(0, rentWritten));
                ArrayPool <byte> .Shared.Return(rented);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Imports the public/private keypair from a PKCS#8 PrivateKeyInfo structure
        /// after decryption, replacing the keys for this object.
        /// </summary>
        /// <param name="source">The bytes of a PKCS#8 PrivateKeyInfo 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 PrivateKeyInfo structure.
        /// </p>
        /// <p>-or-</p>
        /// <p>
        ///   The contents of <paramref name="source" /> indicate the key is for an algorithm
        ///   other than the algorithm represented by this instance.
        /// </p>
        /// <p>-or-</p>
        /// <p>The contents of <paramref name="source" /> represent the key in a format that is not supported.</p>
        /// <p>-or-</p>
        /// <p>
        ///   The algorithm-specific key import failed.
        /// </p>
        /// </exception>
        /// <remarks>
        /// This method only supports the binary (BER/CER/DER) encoding of PrivateKeyInfo.
        /// 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 override unsafe void ImportPkcs8PrivateKey(
            ReadOnlySpan <byte> source,
            out int bytesRead)
        {
            KeyFormatHelper.ReadPkcs8 <ECParameters>(
                s_validOids,
                source,
                EccKeyFormatHelper.FromECPrivateKey,
                out int localRead,
                out ECParameters key);

            fixed(byte *privPin = key.D)
            {
                try
                {
                    ImportParameters(key);
                    bytesRead = localRead;
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(key.D);
                }
            }
        }
Beispiel #9
0
        internal static unsafe Pkcs8Response ImportEncryptedPkcs8PrivateKey(
            ReadOnlySpan <char> password,
            ReadOnlySpan <byte> source,
            out int bytesRead)
        {
            fixed(byte *ptr = &MemoryMarshal.GetReference(source))
            {
                using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length))
                {
                    AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER);
                    int       len    = reader.ReadEncodedValue().Length;
                    source = source.Slice(0, len);

                    try
                    {
                        bytesRead = len;
                        return(ImportPkcs8(source, password));
                    }
                    catch (CryptographicException)
                    {
                    }

                    ArraySegment <byte> decrypted = KeyFormatHelper.DecryptPkcs8(
                        password,
                        manager.Memory.Slice(0, len),
                        out int innerRead);

                    Span <byte> decryptedSpan = decrypted;

                    try
                    {
                        if (innerRead != len)
                        {
                            throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                        }

                        bytesRead = len;
                        return(ImportPkcs8(decryptedSpan));
                    }
                    catch (CryptographicException e)
                    {
                        AsnWriter?pkcs8ZeroPublicKey = RewritePkcs8ECPrivateKeyWithZeroPublicKey(decryptedSpan);

                        if (pkcs8ZeroPublicKey == null)
                        {
                            throw new CryptographicException(SR.Cryptography_Pkcs8_EncryptedReadFailed, e);
                        }

                        try
                        {
                            bytesRead = len;
                            return(ImportPkcs8(pkcs8ZeroPublicKey.EncodeAsSpan()));
                        }
                        catch (CryptographicException)
                        {
                            throw new CryptographicException(SR.Cryptography_Pkcs8_EncryptedReadFailed, e);
                        }
                    }
                    finally
                    {
                        CryptographicOperations.ZeroMemory(decryptedSpan);
                        CryptoPool.Return(decrypted.Array !, clearSize: 0);
                    }
                }
            }
        }