简体   繁体   English

将CryptAcquireContext VB6代码转换为ASP.NET

[英]Convert CryptAcquireContext VB6 code to ASP.NET

I have a very old VB6 code that is used to generate the hash for the password. 我有一个非常旧的VB6代码,用于生成密码的哈希值。 The code uses CryptAcquireContext function along with advapi32.dll to generate the Hash. 该代码使用CryptAcquireContext函数以及advapi32.dll来生成哈希。 There is so much code with variables having hex values etc. The code will take forever to migrate to ASP.NET. 有太多带有十六进制值等变量的代码。这些代码将永远需要迁移到ASP.NET。

We have lots of data encrypted using this Hash code and we don't have a way to decrypt it back to plain text. 我们有很多使用此哈希码加密的数据,我们没有办法将其解密回纯文本。

I need to write similar code in ASP.NET C# that generates the same hash as the VB6 code does. 我需要在ASP.NET C#中编写类似的代码,该代码会生成与VB6代码相同的哈希。

Example: Look at the picture below on how it generates HASH from plaintext: 示例:看下面的图片,了解它如何从纯文本生成HASH:

在此处输入图片说明

Working C# Code in Windows forms only with exception that CryptAcquireContext returns false when the program is run second time: Windows窗体中的工作C#代码仅在以下情况下例外:第二次运行该程序时CryptAcquireContext返回false:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Web;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace CryptoGraphicHash
{
    public partial class Form1 : Form
    {
        static uint CRYPT_NEWKEYSET = 0x8;

        static uint CRYPT_MACHINE_KEYSET = 0x20;

        static uint ALG_CLASS_HASH = 32768;
        // Algorithm types
        static uint ALG_TYPE_ANY = 0;

        static uint PROV_RSA_FULL = 1;
        static uint ALG_SID_SHA = 4;

        static string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
        static uint CALG_SHA = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var test = GenerateHash(textBox1.Text);
            textBox2.Text = test;
        }

        private string GenerateHash(string plaintext)
        {            
            string sContainer = string.Empty;
            string sProvider = MS_DEF_PROV;

            IntPtr hProv = new IntPtr();
            IntPtr hKey = new IntPtr(0);
            IntPtr phHash = new IntPtr();

            try
            {
                bool res = Crypt32.CryptAcquireContext(out hProv, sContainer, sProvider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET);
                if (!res)
                {
                    bool res1 = Crypt32.CryptAcquireContext(out hProv, sContainer, sProvider, PROV_RSA_FULL, CRYPT_NEWKEYSET);
                    if (!res1)
                    {
                        MessageBox.Show("CryptAcquireContext is false for second time so exiting the hash.");
                        var error = Marshal.GetLastWin32Error();
                        Win32Exception test = new Win32Exception(error);
                        MessageBox.Show("Last Win32 error code: " + error);
                        MessageBox.Show("Last Win32 error msg: " + test.Message);
                        return string.Empty;
                    }
                }
                MessageBox.Show("hProv handle value is: " + hProv.ToString());
                //Once we have received the context, next we create hash object                
                bool hashCreateResponse = Crypt32.CryptCreateHash(hProv, CALG_SHA, hKey, 0, ref phHash);
                if (!hashCreateResponse)
                {
                    MessageBox.Show("CryptCreateHash is false so exiting with last win32 error: " + Marshal.GetLastWin32Error());
                    return string.Empty;
                }
                //Hash the data
                byte[] pbData = Encoding.ASCII.GetBytes(plaintext);
                bool hashDataResponse = Crypt32.CryptHashData(phHash, pbData, (uint)plaintext.Length, 0);
                if (!hashDataResponse)
                {
                    MessageBox.Show("CryptHashData is false so exiting.");
                    return string.Empty;
                }
                uint paramLen = 0;
                byte[] paramValue = new byte[0];

                bool getHashParamResponse = Crypt32.CryptGetHashParam(phHash, 0x0002, paramValue, ref paramLen, 0);

                if (234 == Marshal.GetLastWin32Error())
                {
                    paramValue = new byte[paramLen];
                    bool getHashParamResponse1 = Crypt32.CryptGetHashParam(phHash, 0x0002, paramValue, ref paramLen, 0);
                }

                //destroy the key
                Crypt32.CryptDestroyKey(hKey);

                //Destroy the hash object
                Crypt32.CryptDestroyHash(phHash);

                //Release provider handle
                Crypt32.CryptReleaseContext(hProv, 0);
                var sb = new StringBuilder();
                foreach(var item in paramValue)
                {
                    sb.Append(Microsoft.VisualBasic.Strings.Chr(item));
                }
                return sb.ToString();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                MessageBox.Show(ex.InnerException.StackTrace);
                throw ex;
            }
        }
    }


    public class Crypt32
    {
        public enum HashParameters
        {
            HP_ALGID = 0x0001,   // Hash algorithm
            HP_HASHVAL = 0x2, // Hash value
            HP_HASHSIZE = 0x0004 // Hash value size
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptAcquireContext(
out IntPtr phProv,
string pszContainer,
string pszProvider,
uint dwProvType,
uint dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptCreateHash(IntPtr hProv, uint algId, IntPtr hKey, uint dwFlags, ref IntPtr phHash);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptDestroyHash(IntPtr hHash);        

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptDestroyKey(IntPtr phKey);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, uint dataLen, uint flags);

        [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern bool CryptReleaseContext(IntPtr hProv,Int32 dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptGetHashParam(IntPtr hHash,
        uint dwParam,
        Byte[] pbData,
        ref uint pdwDataLen,
        uint dwFlags);
        //public static extern bool CryptGetHashParam(IntPtr hHash, uint dwParam, [Out] byte[] pbData, [In, Out] uint pdwDataLen, uint dwFlags);
    }   
}

You might consider using Platform Invoke Services (PInvoke) to call advapi32.dll functions from .NET. 您可能会考虑使用平台调用服务(PInvoke)从.NET调用advapi32.dll函数。 This might speed up the migration process. 这可能会加快迁移过程。

You can find signatures on http://pinvoke.net 您可以在http://pinvoke.net上找到签名

So finally with help of Joe's suggestion, PInvoke documentation and some code tweaks found on stack over flow, I was able to create a successful working windows form application that has 2 textboxes and a button. 因此,最终,在Joe的建议,PInvoke文档以及在堆栈上流发现的一些代码调整的帮助下,我能够创建一个成功的工作Windows窗体应用程序,该应用程序具有2个文本框和一个按钮。 Enter plaintext in first textbox and click the button to get hash value in the second textbox. 在第一个文本框中输入纯文本,然后单击按钮在第二个文本框中获取哈希值。 The complete code is: 完整的代码是:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Web;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace CryptoGraphicHash
{
    public partial class Form1 : Form
    {
        static uint CRYPT_NEWKEYSET = 0x8;

        static uint CRYPT_MACHINE_KEYSET = 0x20;

        static uint ALG_CLASS_HASH = 32768;
        // Algorithm types
        static uint ALG_TYPE_ANY = 0;

        static uint PROV_RSA_FULL = 1;
        static uint ALG_SID_SHA = 4;

        static string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
        static uint CALG_SHA = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var test = GenerateHash(textBox1.Text);
            textBox2.Text = test;
        }

        private void HandleWin32Error()
        {
            var error = Marshal.GetLastWin32Error();
            Win32Exception ex = new Win32Exception(error);
            MessageBox.Show("Last Win32 error code: " + error);
            MessageBox.Show("Last Win32 error msg: " + ex.Message);
        }

        private string GenerateHash(string plaintext)
        {            
            string sContainer = string.Empty;
            string sProvider = MS_DEF_PROV;

            IntPtr hProv = new IntPtr();
            IntPtr hKey = new IntPtr(0);
            IntPtr phHash = new IntPtr();

            try
            {
                bool res = Crypt32.CryptAcquireContext(out hProv, sContainer, sProvider, PROV_RSA_FULL, 0);
                if (!res)
                {
                    MessageBox.Show("CryptAcquireContext is false for first time so will try again with CRYPT_NEWKEYSET.");
                    HandleWin32Error();
                    bool res1 = Crypt32.CryptAcquireContext(out hProv, sContainer, sProvider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET + CRYPT_NEWKEYSET);
                    if (!res1)
                    {
                        MessageBox.Show("CryptAcquireContext is false for second time so exiting the hash.");
                        HandleWin32Error();
                        return string.Empty;
                    }
                }
                MessageBox.Show("hProv handle value is: " + hProv.ToString());
                //Once we have received the context, next we create hash object                
                bool hashCreateResponse = Crypt32.CryptCreateHash(hProv, CALG_SHA, hKey, 0, ref phHash);
                if (!hashCreateResponse)
                {
                    MessageBox.Show("CryptCreateHash is false so exiting with last win32 error: " + Marshal.GetLastWin32Error());
                    return string.Empty;
                }
                //Hash the data
                byte[] pbData = Encoding.ASCII.GetBytes(plaintext);
                bool hashDataResponse = Crypt32.CryptHashData(phHash, pbData, (uint)plaintext.Length, 0);
                if (!hashDataResponse)
                {
                    MessageBox.Show("CryptHashData is false so exiting.");
                    return string.Empty;
                }
                uint paramLen = 0;
                byte[] paramValue = new byte[0];

                bool getHashParamResponse = Crypt32.CryptGetHashParam(phHash, 0x0002, paramValue, ref paramLen, 0);

                if (234 == Marshal.GetLastWin32Error())
                {
                    paramValue = new byte[paramLen];
                    bool getHashParamResponse1 = Crypt32.CryptGetHashParam(phHash, 0x0002, paramValue, ref paramLen, 0);
                }

                //destroy the key
                Crypt32.CryptDestroyKey(hKey);

                //Destroy the hash object
                Crypt32.CryptDestroyHash(phHash);

                //Release provider handle
                Crypt32.CryptReleaseContext(hProv, 0);
                var sb = new StringBuilder();
                foreach(var item in paramValue)
                {
                    sb.Append(Microsoft.VisualBasic.Strings.Chr(item));
                }
                return sb.ToString();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                MessageBox.Show(ex.InnerException.StackTrace);
                throw ex;
            }
        }
    }


    public class Crypt32
    {
        public enum HashParameters
        {
            HP_ALGID = 0x0001,   // Hash algorithm
            HP_HASHVAL = 0x2, // Hash value
            HP_HASHSIZE = 0x0004 // Hash value size
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptAcquireContext(
out IntPtr phProv,
string pszContainer,
string pszProvider,
uint dwProvType,
uint dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptCreateHash(IntPtr hProv, uint algId, IntPtr hKey, uint dwFlags, ref IntPtr phHash);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptDestroyHash(IntPtr hHash);        

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptDestroyKey(IntPtr phKey);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, uint dataLen, uint flags);

        [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern bool CryptReleaseContext(IntPtr hProv,Int32 dwFlags);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptGetHashParam(IntPtr hHash,
        uint dwParam,
        Byte[] pbData,
        ref uint pdwDataLen,
        uint dwFlags);
        //public static extern bool CryptGetHashParam(IntPtr hHash, uint dwParam, [Out] byte[] pbData, [In, Out] uint pdwDataLen, uint dwFlags);
    }   
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM