예제 #1
0
        /// <summary>
        /// Encrypts a block of data.
        /// </summary>
        /// <param name="hKey">
        /// The handle of the key to use to encrypt the data. This handle is obtained from one of the key creation functions, such as <see cref="BCryptGenerateSymmetricKey(SafeAlgorithmHandle, byte[], byte[], BCryptGenerateSymmetricKeyFlags)"/>, <see cref="BCryptGenerateKeyPair(SafeAlgorithmHandle, int)"/>, or <see cref="BCryptImportKey(SafeAlgorithmHandle, string, byte[], SafeKeyHandle, byte[], BCryptImportKeyFlags)"/>.
        /// </param>
        /// <param name="pbInput">
        /// The address of a buffer that contains the plaintext to be encrypted. The cbInput parameter contains the size of the plaintext to encrypt.
        /// </param>
        /// <param name="pPaddingInfo">
        /// A pointer to a structure that contains padding information. This parameter is only used with asymmetric keys and authenticated encryption modes. If an authenticated encryption mode is used, this parameter must point to a BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO structure. If asymmetric keys are used, the type of structure this parameter points to is determined by the value of the dwFlags parameter. Otherwise, the parameter must be set to NULL.
        /// </param>
        /// <param name="pbIV">
        /// The address of a buffer that contains the initialization vector (IV) to use during encryption. The cbIV parameter contains the size of this buffer. This function will modify the contents of this buffer. If you need to reuse the IV later, make sure you make a copy of this buffer before calling this function.
        /// This parameter is optional and can be NULL if no IV is used.
        /// The required size of the IV can be obtained by calling the <see cref="BCryptGetProperty(SafeHandle, string, BCryptGetPropertyFlags)"/> function to get the BCRYPT_BLOCK_LENGTH property.This will provide the size of a block for the algorithm, which is also the size of the IV.
        /// </param>
        /// <param name="dwFlags">
        /// A set of flags that modify the behavior of this function. The allowed set of flags depends on the type of key specified by the hKey parameter.
        /// </param>
        /// <returns>The encrypted ciphertext.</returns>
        public static unsafe ArraySegment <byte> BCryptEncrypt(
            SafeKeyHandle hKey,
            byte[] pbInput,
            void *pPaddingInfo,
            byte[] pbIV,
            BCryptEncryptFlags dwFlags)
        {
            int length;

            BCryptEncrypt(
                hKey,
                pbInput.AsSpan(),
                pPaddingInfo,
                pbIV,
                null,
                out length,
                dwFlags).ThrowOnError();

            byte[] cipherText = new byte[length];
            BCryptEncrypt(
                hKey,
                pbInput.AsSpan(),
                pPaddingInfo,
                pbIV,
                cipherText,
                out length,
                dwFlags).ThrowOnError();

            return(new ArraySegment <byte>(cipherText, 0, length));
        }
예제 #2
0
 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375391(v=vs.85).aspx
 internal static extern int BCryptDecrypt(
     [In] BCryptKeyHandle hKey,
     [In] byte *pbInput,
     [In] uint cbInput,
     [In] void *pPaddingInfo,
     [In] byte *pbIV,
     [In] uint cbIV,
     [In] byte *pbOutput,
     [In] uint cbOutput,
     [Out] out uint pcbResult,
     [In] BCryptEncryptFlags dwFlags);
예제 #3
0
    internal static extern int BCryptDecrypt(
#endif
        BCryptKeyHandle hKey,
        byte *pbInput,
        uint cbInput,
        void *pPaddingInfo,
        byte *pbIV,
        uint cbIV,
        byte *pbOutput,
        uint cbOutput,
        out uint pcbResult,
        BCryptEncryptFlags dwFlags);
예제 #4
0
        public static unsafe NTSTATUS BCryptDecrypt(
            SafeKeyHandle key,
            ArraySegment <byte>?input,
            void *paddingInfo,
            ArraySegment <byte>?iv,
            ArraySegment <byte>?output,
            out int outputLength,
            BCryptEncryptFlags flags)
        {
            var inputLocal  = input ?? default(ArraySegment <byte>);
            var ivLocal     = iv ?? default(ArraySegment <byte>);
            var outputLocal = output ?? default(ArraySegment <byte>);

            // We have to make sure that the input, which may be null, does
            // not cause a NRE in our fixed expressions below, which cannot do
            // conditional expressions due to C# constraints.
            EnsureNotNullOrEmpty(ref inputLocal);
            EnsureNotNullOrEmpty(ref ivLocal);
            EnsureNotNullOrEmpty(ref outputLocal);

            fixed(byte *pbInput = &inputLocal.Array[inputLocal.Offset])
            {
                fixed(byte *pbOutput = &outputLocal.Array[outputLocal.Offset])
                {
                    fixed(byte *pbIV = &ivLocal.Array[ivLocal.Offset])
                    {
                        // As we call the P/Invoke method, restore any nulls that were originally there.
                        return(BCryptDecrypt(
                                   key,
                                   ArrayOrOriginalNull(inputLocal, pbInput),
                                   inputLocal.Count,
                                   paddingInfo,
                                   ArrayOrOriginalNull(ivLocal, pbIV),
                                   ivLocal.Count,
                                   ArrayOrOriginalNull(outputLocal, pbOutput),
                                   outputLocal.Count,
                                   out outputLength,
                                   flags));
                    }
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricCryptographicKey" /> class.
        /// </summary>
        /// <param name="keyMaterial">The symmetric key.</param>
        /// <param name="symmetricAlgorithmProvider">The symmetric algorithm of the provider creating this key.</param>
        internal SymmetricCryptographicKey(byte[] keyMaterial, SymmetricKeyAlgorithmProvider symmetricAlgorithmProvider)
        {
            Requires.NotNullOrEmpty(keyMaterial, nameof(keyMaterial));
            Requires.NotNull(symmetricAlgorithmProvider, nameof(symmetricAlgorithmProvider));

            this.symmetricAlgorithmProvider = symmetricAlgorithmProvider;

            // Copy the key material so our caller can reuse their buffer.
            this.keyMaterial = new byte[keyMaterial.Length];
            Array.Copy(keyMaterial, this.keyMaterial, keyMaterial.Length);

            this.Name = symmetricAlgorithmProvider.Name;
            this.Mode = symmetricAlgorithmProvider.Mode;
            this.Padding = symmetricAlgorithmProvider.Padding;

            if (this.Padding == SymmetricAlgorithmPadding.PKCS7)
            {
                this.flags |= BCryptEncryptFlags.BCRYPT_BLOCK_PADDING;
            }
        }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricCryptographicKey" /> class.
        /// </summary>
        /// <param name="keyMaterial">The symmetric key.</param>
        /// <param name="symmetricAlgorithmProvider">The symmetric algorithm of the provider creating this key.</param>
        internal SymmetricCryptographicKey(byte[] keyMaterial, SymmetricKeyAlgorithmProvider symmetricAlgorithmProvider)
        {
            Requires.NotNullOrEmpty(keyMaterial, nameof(keyMaterial));
            Requires.NotNull(symmetricAlgorithmProvider, nameof(symmetricAlgorithmProvider));

            this.symmetricAlgorithmProvider = symmetricAlgorithmProvider;

            // Copy the key material so our caller can reuse their buffer.
            this.keyMaterial = new byte[keyMaterial.Length];
            Array.Copy(keyMaterial, this.keyMaterial, keyMaterial.Length);

            this.Name    = symmetricAlgorithmProvider.Name;
            this.Mode    = symmetricAlgorithmProvider.Mode;
            this.Padding = symmetricAlgorithmProvider.Padding;

            if (this.Padding == SymmetricAlgorithmPadding.PKCS7)
            {
                this.flags |= BCryptEncryptFlags.BCRYPT_BLOCK_PADDING;
            }
        }
예제 #7
0
        /// <summary>
        /// Decrypts a block of data.
        /// </summary>
        /// <param name="hKey">
        /// The handle of the key to use to decrypt the data. This handle is obtained from one of the key creation functions, such as <see cref="BCryptGenerateSymmetricKey(SafeAlgorithmHandle, byte[], byte[], BCryptGenerateSymmetricKeyFlags)"/>, <see cref="BCryptGenerateKeyPair(SafeAlgorithmHandle, int)"/>, or <see cref="BCryptImportKey(SafeAlgorithmHandle, string, byte[], SafeKeyHandle, byte[], BCryptImportKeyFlags)"/>.
        /// </param>
        /// <param name="pbInput">
        /// The address of a buffer that contains the ciphertext to be decrypted. For more information, see Remarks.
        /// </param>
        /// <param name="pPaddingInfo">
        /// A pointer to a structure that contains padding information. This parameter is only used with asymmetric keys and authenticated encryption modes. If an authenticated encryption mode is used, this parameter must point to a BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO structure. If asymmetric keys are used, the type of structure this parameter points to is determined by the value of the <paramref name="dwFlags"/> parameter. Otherwise, the parameter must be set to NULL.
        /// </param>
        /// <param name="pbIV">
        /// The address of a buffer that contains the initialization vector (IV) to use during decryption. This function will modify the contents of this buffer. If you need to reuse the IV later, make sure you make a copy of this buffer before calling this function.
        /// This parameter is optional and can be NULL if no IV is used.
        /// The required size of the IV can be obtained by calling the <see cref="BCryptGetProperty(SafeHandle, string, BCryptGetPropertyFlags)"/> function to get the <see cref="PropertyNames.BCRYPT_BLOCK_LENGTH"/> property. This will provide the size of a block for the algorithm, which is also the size of the IV.
        /// </param>
        /// <param name="dwFlags">
        /// A set of flags that modify the behavior of this function. The allowed set of flags depends on the type of key specified by the <paramref name="hKey"/> parameter.
        /// </param>
        /// <returns>Returns a status code that indicates the success or failure of the function.</returns>
        public static unsafe ArraySegment <byte> BCryptDecrypt(
            SafeKeyHandle hKey,
            byte[] pbInput,
            void *pPaddingInfo,
            byte[] pbIV,
            BCryptEncryptFlags dwFlags)
        {
            int length;

            BCryptDecrypt(
                hKey,
                pbInput,
                pbInput.Length,
                pPaddingInfo,
                pbIV,
                pbIV?.Length ?? 0,
                null,
                0,
                out length,
                dwFlags).ThrowOnError();

            byte[] plainText = new byte[length];
            BCryptDecrypt(
                hKey,
                pbInput,
                pbInput.Length,
                pPaddingInfo,
                pbIV,
                pbIV?.Length ?? 0,
                plainText,
                plainText.Length,
                out length,
                dwFlags).ThrowOnError();

            // Padding may result in a shorter output than previously estimated.
            return(new ArraySegment <byte>(plainText, 0, length));
        }
예제 #8
0
 public static unsafe extern NTSTATUS BCryptDecrypt(
     SafeKeyHandle hKey,
     byte* pbInput,
     int cbInput,
     void* pPaddingInfo,
     byte* pbIV,
     int cbIV,
     byte* pbOutput,
     int cbOutput,
     out int pcbResult,
     BCryptEncryptFlags dwFlags);