using System; using System.Runtime.InteropServices; namespace SharpChrome { public class BCrypt { // adapted from https://github.com/AArnott/pinvoke/blob/master/src/BCrypt/ // Author: @AArnott // License: MIT #region Structs [StructLayout(LayoutKind.Sequential)] //[OfferIntPtrPropertyAccessors] public unsafe partial struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO { public const uint BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1; public int cbSize; public uint dwInfoVersion; public byte* pbNonce; public int cbNonce; public byte* pbAuthData; public int cbAuthData; public byte* pbTag; public int cbTag; public byte* pbMacContext; public int cbMacContext; public int cbAAD; public long cbData; public AuthModeFlags dwFlags; public static BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO Create() { return new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO { cbSize = Marshal.SizeOf(typeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO)), dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION, }; } } #endregion #region Enums [Flags] public enum AuthModeFlags { None = 0x0, BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG = 0x1, BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG = 0x2, } [Flags] public enum BCryptCloseAlgorithmProviderFlags { None = 0x0, } [Flags] public enum BCryptOpenAlgorithmProviderFlags { None = 0x0, BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x8, BCRYPT_HASH_REUSABLE_FLAG = 0x20, BCRYPT_MULTI_FLAG = 0x40, } public enum BCryptSetPropertyFlags { None = 0x0, } [Flags] public enum BCryptGenerateSymmetricKeyFlags { None = 0x0, } [Flags] public enum BCryptEncryptFlags { None = 0x0, BCRYPT_BLOCK_PADDING = 1, BCRYPT_PAD_NONE = 0x1, BCRYPT_PAD_PKCS1 = 0x2, BCRYPT_PAD_OAEP = 0x4, } # endregion #region Functions [DllImport("BCrypt", SetLastError = true, ExactSpelling = true)] public static extern uint BCryptDestroyKey( IntPtr hKey); [DllImport("BCrypt", SetLastError = true, ExactSpelling = true)] public static extern uint BCryptCloseAlgorithmProvider( IntPtr algorithmHandle, BCryptCloseAlgorithmProviderFlags flags = BCryptCloseAlgorithmProviderFlags.None); [DllImport("BCrypt", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern uint BCryptOpenAlgorithmProvider( out SafeAlgorithmHandle phAlgorithm, string pszAlgId, string pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags); [DllImport("BCrypt", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern uint BCryptSetProperty( SafeHandle hObject, string pszProperty, string pbInput, int cbInput, BCryptSetPropertyFlags dwFlags = BCryptSetPropertyFlags.None); [DllImport("BCrypt", SetLastError = true)] public static extern uint BCryptGenerateSymmetricKey( SafeAlgorithmHandle hAlgorithm, out SafeKeyHandle phKey, byte[] pbKeyObject, int cbKeyObject, byte[] pbSecret, int cbSecret, BCryptGenerateSymmetricKeyFlags flags = BCryptGenerateSymmetricKeyFlags.None); [DllImport("BCrypt", SetLastError = true)] public static unsafe extern uint BCryptDecrypt( SafeKeyHandle hKey, byte* pbInput, int cbInput, void* pPaddingInfo, byte* pbIV, int cbIV, byte* pbOutput, int cbOutput, out int pcbResult, BCryptEncryptFlags dwFlags); #endregion #region Classes public class SafeKeyHandle : SafeHandle { public static readonly SafeKeyHandle Null = new SafeKeyHandle(); public SafeKeyHandle() : base(IntPtr.Zero, true) { } public SafeKeyHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(IntPtr.Zero, ownsHandle) { this.SetHandle(preexistingHandle); } public override bool IsInvalid => this.handle == IntPtr.Zero; protected override bool ReleaseHandle() { // 0x0 == STATUS_SUCCESS return BCryptDestroyKey(this.handle) == 0x0; } } public class SafeAlgorithmHandle : SafeHandle { public static readonly SafeAlgorithmHandle Null = new SafeAlgorithmHandle(); public SafeAlgorithmHandle() : base(IntPtr.Zero, true) { } public SafeAlgorithmHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(IntPtr.Zero, ownsHandle) { this.SetHandle(preexistingHandle); } public override bool IsInvalid => this.handle == IntPtr.Zero; protected override bool ReleaseHandle() { // 0x0 == STATUS_SUCCESS return BCryptCloseAlgorithmProvider(this.handle, 0) == 0; } } #endregion #region Helperse public static void BCRYPT_INIT_AUTH_MODE_INFO(out BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO _AUTH_INFO_STRUCT_) { _AUTH_INFO_STRUCT_ = new BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(); _AUTH_INFO_STRUCT_.cbSize = Marshal.SizeOf(typeof(BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO)); _AUTH_INFO_STRUCT_.dwInfoVersion = 1; } #endregion } }