/// <summary> /// Encrypts data according to a specified protection type. /// </summary> /// <param name="type">One of the <see cref="ProtectionType"/> values.</param> /// <param name="data">The data to encrypt.</param> /// <param name="offset">The zero-based position in the <i>data</i> parameter at which to begin encrypting.</param> /// <param name="size">The number of bytes to encrypt.</param> /// <param name="entropy">Additional entropy to use during the encryption process. This parameter can be set to null.</param> /// <exception cref="ArgumentNullException"><i>data</i> is a null reference (<b>Nothing</b> in Visual Basic).</exception> /// <exception cref="ArgumentException">The specified <i>offset</i> or <i>size</i> exceeds the size of buffer.</exception> /// <exception cref="CryptographicException">An error occurs during the encryption process. Under some circumstances, Microsoft cryptographic service providers may not allow encryption when used in France. This may occur on down-level platforms such as Windows 98 and Windows NT 4.0, depending on the system's configuration and the version of the CSPs.</exception> /// <returns>An array of encrypted bytes.</returns> /// <remarks>The number of the returned bytes will be larger than the number of input bytes.</remarks> public byte[] ProtectData(ProtectionType type, byte[] data, int offset, int size, byte[] entropy) { if (m_Disposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (data == null) { throw new ArgumentNullException(); } if (offset < 0 || offset + size > data.Length || !Enum.IsDefined(typeof(ProtectionType), type)) { throw new ArgumentException(); } DataBlob input = new DataBlob(); DataBlob entr = new DataBlob(); DataBlob output = new DataBlob(); try { // initialize input structure input.cbData = size; input.pbData = Marshal.AllocHGlobal(size); Marshal.Copy(data, offset, input.pbData, size); // initialize entropy structure if (entropy == null) { entr.cbData = 0; entr.pbData = IntPtr.Zero; } else { entr.cbData = entropy.Length; entr.pbData = Marshal.AllocHGlobal(entr.cbData); Marshal.Copy(entropy, 0, entr.pbData, entr.cbData); } // initialize output structure output.cbData = 0; output.pbData = IntPtr.Zero; // call the function and check for errors int flags = 0; if (type == ProtectionType.LocalMachine) { flags = flags | SecurityConstants.CRYPTPROTECT_LOCAL_MACHINE; } if (!Environment.UserInteractive) { flags = flags | SecurityConstants.CRYPTPROTECT_UI_FORBIDDEN; } if (SspiProvider.CryptProtectData(ref input, "", ref entr, IntPtr.Zero, IntPtr.Zero, flags, ref output) == 0 || output.pbData == IntPtr.Zero) { throw new CryptographicException("The data could not be protected."); } byte[] ret = new byte[output.cbData]; Marshal.Copy(output.pbData, ret, 0, output.cbData); return(ret); } finally { if (input.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(input.pbData); } if (entr.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(entr.pbData); } if (output.pbData != IntPtr.Zero) { Marshal.FreeHGlobal(output.pbData); } } }