Example #1
0
        /// <summary>
        /// See <see cref="ProtectedData"/>.
        /// </summary>
        /// <param name="encryptedData">Data to unprotect.</param>
        /// <param name="optionalEntropy">Additional material to be added to the symmetric key used for encryption.</param>
        /// <param name="scope">See <see cref="DataProtectionScope"/>.</param>
        /// <returns>Plain text data.</returns>
        /// <exception cref="ArgumentNullException">The specified parameter is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="CryptographicException">Exception when executing unmanaged code.</exception>
        /// <permission cref="CryptographicPermission">Demand for decryption permission.</permission>
        public static byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            // Verify input
            if (encryptedData == null || encryptedData.Length == 0)
            {
                throw new ArgumentNullException("encryptedData");
            }
            if (!IsValidScope(scope))
            {
                throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.InvalidDataProtectionScope]);
            }

            // Demand Permission
            new CryptographicPermission(CryptographicPermissionFlags.Decrypt).Demand();
            // Assert UnamanagedCode (replaced by the SuppressUnmanagedCodeSecurity attribute of the Win32Native class

            // Initialize vars.
            // Check to see if the entropy is null
            if (optionalEntropy == null)
            {
                // Allocate something
                optionalEntropy = new byte[0];
            }

            Win32Native.CRYPTOAPI_BLOB plainTextBlob = new Win32Native.CRYPTOAPI_BLOB();

            GCHandle encryptedDataHandle = GCHandle.Alloc(encryptedData, GCHandleType.Pinned);
            GCHandle entropyHandle       = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);

            try
            {
                Win32Native.CRYPTPROTECT_PROMPTSTRUCT prompt = new Win32Native.CRYPTPROTECT_PROMPTSTRUCT(0);

                Win32Native.CRYPTOAPI_BLOB encryptedDataBlob = new Win32Native.CRYPTOAPI_BLOB();
                encryptedDataBlob.cbData = (uint)encryptedData.Length;
                encryptedDataBlob.pbData = encryptedDataHandle.AddrOfPinnedObject();

                Win32Native.CRYPTOAPI_BLOB entropyBlob = new Win32Native.CRYPTOAPI_BLOB();
                entropyBlob.cbData = (uint)optionalEntropy.Length;
                entropyBlob.pbData = entropyHandle.AddrOfPinnedObject();

                if (!Win32Native.CryptUnprotectData(ref encryptedDataBlob,
                                                    null,
                                                    ref entropyBlob,
                                                    IntPtr.Zero,
                                                    ref prompt,
                                                    (uint)scope,
                                                    ref plainTextBlob))
                {
                    throw new CryptographicException(Resource.ResourceManager[Resource.MessageKey.UnprotectDataException], new Win32Exception(Marshal.GetLastWin32Error()));
                }

                if (plainTextBlob.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException(Resource.ResourceManager[Resource.MessageKey.OutOfMemoryException, "plainTextBlob"]);
                }

                byte[] plainText = new byte[plainTextBlob.cbData];
                Marshal.Copy(plainTextBlob.pbData, plainText, 0, plainText.Length);

                return(plainText);
            }
            finally
            {
                // Free handles
                if (encryptedDataHandle.IsAllocated)
                {
                    encryptedDataHandle.Free();
                }
                if (entropyHandle.IsAllocated)
                {
                    entropyHandle.Free();
                }
                //Free the unmanaged resource ...
                // Free and erase the plainTextBlob
                if (plainTextBlob.pbData != IntPtr.Zero)
                {
                    Win32Native.ZeroMemory(plainTextBlob.pbData, plainTextBlob.cbData);
                    Win32Native.LocalFree(plainTextBlob.pbData);
                }
            }
        }
Example #2
0
        /// <summary>
        /// This function performs encryption on the data in a byte array input data.
        /// If <see cref="DataProtectionScope.CurrentUser"/> is specified, only a user
        /// with the same logon credentials as the encrypter can decrypt the data.
        /// <b>Warning</b>If the logon credentials are lost or forgotten, the data is usually unrecoverable.
        /// If the <see cref="DataProtectionScope.LocalMachine"/> is used, the encryption and decryption must be done on the same computer
        /// therefore any user on the same computer where the data was encrypted can recover the data.
        /// </summary>
        /// <remarks>
        /// The function creates a session key to perform the encryption.
        /// The session key is rederived when the data is to be decrypted.
        /// The function also adds a message authentication code (MAC), which is a keyed integrity check, to the encrypted data to guard against data tampering.
        /// </remarks>
        /// <param name="userData">Data to be protected. This array should be erased after use with <see cref="Array.Clear"/>.</param>
        /// <param name="optionalEntropy">Additional material to be added to the symmetric key used for encryption.</param>
        /// <param name="scope">See <see cref="DataProtectionScope"/>.</param>
        /// <returns>Protected data.</returns>
        /// <exception cref="ArgumentNullException">The specified parameter is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="CryptographicException">Exception when executing unmanaged code.</exception>
        /// <permission cref="CryptographicPermission">Demand for encryption permission.</permission>
        public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            // Verify input
            if (userData == null)
            {
                throw new ArgumentNullException("userData");
            }
            if (!IsValidScope(scope))
            {
                throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.InvalidDataProtectionScope]);
            }

            // Demand Permission
            new CryptographicPermission(CryptographicPermissionFlags.Encrypt).Demand();
            // Assert UnamanagedCode (replaced by the SuppressUnmanagedCodeSecurity attribute of the Win32Native class

            // Check to see if the entropy is null
            if (optionalEntropy == null)
            {
                // Allocate something
                optionalEntropy = new byte[0];
            }

            Win32Native.CRYPTOAPI_BLOB cipherTextBlob = new Win32Native.CRYPTOAPI_BLOB();

            // This prevents the garbage collector from moving the object and hence
            // undermines the efficiency of the garbage collector. We 'll release
            // the reference on the finally block.
            GCHandle userDataHandle = GCHandle.Alloc(userData, GCHandleType.Pinned);
            GCHandle entropyHandle  = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);

            try
            {
                Win32Native.CRYPTPROTECT_PROMPTSTRUCT prompt = new Win32Native.CRYPTPROTECT_PROMPTSTRUCT(0);

                Win32Native.CRYPTOAPI_BLOB plainTextBlob = new Win32Native.CRYPTOAPI_BLOB();
                plainTextBlob.cbData = (uint)userData.Length;
                plainTextBlob.pbData = userDataHandle.AddrOfPinnedObject();

                Win32Native.CRYPTOAPI_BLOB entropyBlob = new Win32Native.CRYPTOAPI_BLOB();
                entropyBlob.cbData = (uint)optionalEntropy.Length;
                entropyBlob.pbData = entropyHandle.AddrOfPinnedObject();

                if (!Win32Native.CryptProtectData(ref plainTextBlob,
                                                  null,
                                                  ref entropyBlob,
                                                  IntPtr.Zero,
                                                  ref prompt,
                                                  (uint)scope,
                                                  ref cipherTextBlob))
                {
                    throw new CryptographicException(Resource.ResourceManager[Resource.MessageKey.ProtectDataException], new Win32Exception(Marshal.GetLastWin32Error()));
                }

                //Check returned data
                if (cipherTextBlob.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException(Resource.ResourceManager[Resource.MessageKey.OutOfMemoryException, "cipherTextBlob"]);
                }

                // Move encrypted data to the returned array
                byte[] cipherText = new byte[cipherTextBlob.cbData];
                Marshal.Copy(cipherTextBlob.pbData, cipherText, 0, cipherText.Length);

                return(cipherText);
            }
            finally
            {
                // Free the allocated handles
                if (userDataHandle.IsAllocated)
                {
                    userDataHandle.Free();
                }
                if (entropyHandle.IsAllocated)
                {
                    entropyHandle.Free();
                }
                //Free the unmanaged resource ...
                // Free and erase the cipherTextBlob
                if (cipherTextBlob.pbData != IntPtr.Zero)
                {
                    Win32Native.ZeroMemory(cipherTextBlob.pbData, cipherTextBlob.cbData);
                    Win32Native.LocalFree(cipherTextBlob.pbData);
                }
            }
        }