我想请求帮助重构C#代码。
目标是删除所有外部WinApi调用,并使用System.Security.Cryptography命名空间中的方法替换它们。
private static IntPtr GenerateKey(IntPtr hCryptProv, byte[] keyData)
{
var hHash = IntPtr.Zero;
Win32.CryptCreateHash(hCryptProv, Win32.CALG_MD5, IntPtr.Zero, 0, ref hHash);
var len = (uint)keyData.Length;
Win32.CryptHashData(hHash, keyData, len, 0);
var hKey = IntPtr.Zero;
Win32.CryptDeriveKey(hCryptProv, Win32.CALG_3DES, hHash, 0, ref hKey);
if (hHash != IntPtr.Zero) Win32.CryptDestroyHash(hHash);
return hKey;
}
public static byte[] Encrypt(byte[] dataToEncrypt)
{
var keyData = Encoding.ASCII.GetBytes("{2B9B4443-74CE-42A8-8803-076B136B5967}");
var size = (uint)dataToEncrypt.Length;
var buffer = new byte[size * 2];
Array.Copy(dataToEncrypt, 0, buffer, 0, size);
var hCryptProv = IntPtr.Zero;
bool gotcsp = Win32.CryptAcquireContext(ref hCryptProv, null, null, Win32.PROV_RSA_FULL, Win32.CRYPT_VERIFYCONTEXT | Win32.CRYPT_MACHINE_KEYSET);
if (!gotcsp)
{
Win32.CryptAcquireContext(ref hCryptProv, null, null, Win32.PROV_RSA_FULL, Win32.CRYPT_NEWKEYSET | Win32.CRYPT_VERIFYCONTEXT | Win32.CRYPT_MACHINE_KEYSET);
}
if (hCryptProv == IntPtr.Zero) return null;
var hKey = GenerateKey(hCryptProv, keyData);
Win32.CryptEncrypt(hKey, IntPtr.Zero, 1, 0, buffer, ref size, size*2);
var encryptedData = new byte[size];
Array.Copy(buffer, 0, encryptedData, 0, size);
if (hKey != IntPtr.Zero) Win32.CryptDestroyKey(hKey);
if (hCryptProv != IntPtr.Zero) Win32.CryptReleaseContext(hCryptProv, 0);
return encryptedData;
}
/// <summary>
/// WinAPI Imports
/// </summary>
internal class Win32
{
public const uint PROV_RSA_FULL = 1;
public const uint NTE_BAD_KEYSET = 0x80090016;
public const uint CRYPT_NEWKEYSET = 0x00000008;
public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
public const uint CRYPT_MACHINE_KEYSET = 0x00000020;
public const uint ALG_CLASS_HASH = (4 << 13);
public const uint ALG_SID_MD5 = 3;
public const uint CALG_MD5 = (ALG_CLASS_HASH | ALG_SID_MD5);
public const uint ALG_CLASS_DATA_ENCRYPT = (3 << 13);
public const uint ALG_TYPE_BLOCK = (3 << 9);
public const uint ALG_SID_3DES = 3;
public const uint CALG_3DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptCreateHash(IntPtr hProv, uint Algid, IntPtr hKey, uint dwFlags, ref IntPtr hHash);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptHashData(IntPtr hHash, [In, Out] byte[] pbData, uint dwDataLen, uint dwSize);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDeriveKey(IntPtr hProv, uint Algid, IntPtr hHash, uint dwFlags, ref IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, int Final, uint dwFlags, [In, Out] byte[] pbData, ref uint pdwDataLen, uint dwBufLen);
}
我尝试过不同的组合,选项和加密提供程序,使用System.Security.Cryptography创建类似的方法没有问题,但问题是我需要一个替换代码的方法。 这意味着,为了加密传递相同的数据,我必须得到相同的结果。这是一个问题。我对加密的了解肯定不是很深入,不能考虑到这种方法的所有细微差别。
你能帮我解决这个问题吗?我不是要给我一个加密教程的链接,但要告诉我应该使用哪些选项的方法。
[2017-03-28 11:27GMT]其他信息:
我真的不认为它会有所帮助,但我完成了一个实验性代码:
public static List<byte> Encrypt(byte[] toEncrypt)
{
var databytes = Encoding.ASCII.GetBytes("{2B9B4443-74CE-42A8-8803-076B136B5967}");
var hashmd5 = new MD5CryptoServiceProvider();
var keyArray = hashmd5.ComputeHash(databytes);
hashmd5.Clear();
var pdb = new PasswordDeriveBytes(keyArray, new byte[0]);
var hashKey = pdb.CryptDeriveKey("TripleDES", "MD5", 0, new byte[8]);
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = hashKey;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
var cTransform = tdes.CreateEncryptor();
var resultArray = cTransform.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length);
tdes.Clear();
return resultArray.ToList();
}
还有许多其他变种,但没有任何能给我正确的结果:
来源数据:
private byte[] dataToEncrypt = {224,111,176,138,238,238,238,239,115,109,201,144,89,58,161,0,0,0,0,0,0,0,0};
原始功能重新出现:
private byte[] originalResult = {31,173,65,161,199,249,73,200,210,74,156,21,36,160,94,137,71,205,15,206,99,105,40,83};
示例函数返回:
private byte[] sampleResult = {211,29,187,125,82,9,240,177,199,133,135,7,132,166,166,164,189,36,126,186,104,79,53,159};
答案 0 :(得分:0)
我至少丢失了一个小时,因为我认为您的代码使用了RSA(我被PROV_RSA_FULL
误导了)......实际上它只是在进行3DES加密......
var keyData = Encoding.ASCII.GetBytes("{2B9B4443-74CE-42A8-8803-076B136B5967}");
byte[] key;
using (PasswordDeriveBytes pdb = new PasswordDeriveBytes(keyData, null))
{
key = pdb.CryptDeriveKey("TripleDES", "MD5", 0, new byte[8]);
//Debug.WriteLine(BitConverter.ToString(key));
}
using (var prov = new TripleDESCryptoServiceProvider())
{
using (var encryptor = prov.CreateEncryptor(key, new byte[8]))
{
byte[] encrypted = encryptor.TransformFinalBlock(bytes2, 0, bytes2.Length);
//Debug.WriteLine(BitConverter.ToString(encrypted));
}
}
出于好奇,我会发布原始C#代码的修改版本...我想调试一下生成的密钥,但是在CryptoAPI中导出它很复杂,然后原始代码不是就像我会写的那样: - )
private static IntPtr GenerateKey(IntPtr hProv, byte[] keyData)
{
var hHash = IntPtr.Zero;
try
{
bool check = Win32.CryptCreateHash(hProv, Win32.CALG_MD5, IntPtr.Zero, 0, out hHash);
if (!check)
{
throw new Win32Exception();
}
check = Win32.CryptHashData(hHash, keyData, keyData.Length, 0);
if (!check)
{
throw new Win32Exception();
}
IntPtr hKey;
check = Win32.CryptDeriveKey(hProv, Win32.CALG_3DES, hHash, Win32.CRYPT_EXPORTABLE, out hKey);
if (!check)
{
throw new Win32Exception();
}
return hKey;
}
finally
{
if (hHash != IntPtr.Zero)
{
Win32.CryptDestroyHash(hHash);
}
}
}
public static byte[] Encrypt(byte[] plainText)
{
var keyData = Encoding.ASCII.GetBytes("{2B9B4443-74CE-42A8-8803-076B136B5967}");
IntPtr hCryptProv = IntPtr.Zero;
IntPtr hKey = IntPtr.Zero;
try
{
bool check = Win32.CryptAcquireContext(out hCryptProv, null, null, Win32.PROV_RSA_FULL, Win32.CRYPT_VERIFYCONTEXT | Win32.CRYPT_MACHINE_KEYSET);
if (!check)
{
check = Win32.CryptAcquireContext(out hCryptProv, null, null, Win32.PROV_RSA_FULL, Win32.CRYPT_NEWKEYSET | Win32.CRYPT_VERIFYCONTEXT | Win32.CRYPT_MACHINE_KEYSET);
if (!check)
{
throw new Win32Exception();
}
}
hKey = GenerateKey(hCryptProv, keyData);
//byte[] key = ExportSymmetricKey(hCryptProv, hKey);
//Debug.WriteLine(BitConverter.ToString(key));
var size = plainText.Length;
check = Win32.CryptEncrypt(hKey, IntPtr.Zero, 1, 0, null, ref size, 0);
if (!check)
{
throw new Win32Exception();
}
var cypherText = new byte[size];
Array.Copy(plainText, cypherText, plainText.Length);
size = plainText.Length;
check = Win32.CryptEncrypt(hKey, IntPtr.Zero, 1, 0, cypherText, ref size, cypherText.Length);
if (!check)
{
throw new Win32Exception();
}
return cypherText;
}
finally
{
if (hKey != IntPtr.Zero)
{
Win32.CryptDestroyKey(hKey);
}
if (hCryptProv != IntPtr.Zero)
{
Win32.CryptReleaseContext(hCryptProv, 0);
}
}
}
// Based on https://books.google.it/books?id=aL3P3eJdiREC&pg=PT271&lpg=PT271&dq=PROV_RSA_FULL+CryptEncrypt&source=bl&ots=STsuConTHr&sig=W-BWwch8aZ-RqFb8N67rMHTrqYc&hl=it&sa=X&ved=0ahUKEwit2qKnlfvSAhWCtRQKHbL9BbQQ6AEIQzAF#v=onepage&q=PROV_RSA_FULL%20CryptEncrypt&f=false
// Page 248
private static byte[] ExportSymmetricKey(IntPtr hProv, IntPtr hKey)
{
IntPtr hExpKey = IntPtr.Zero;
try
{
bool check = Win32.CryptGenKey(hProv, 1 /* AT_KEYEXCHANGE */, 1024 << 16, out hExpKey);
if (!check)
{
throw new Win32Exception();
}
int size = 0;
check = Win32.CryptExportKey(hKey, hExpKey, 1 /* SIMPLEBLOB */, 0, null, ref size);
if (!check)
{
throw new Win32Exception();
}
var bytes = new byte[size];
check = Win32.CryptExportKey(hKey, hExpKey, 1 /* SIMPLEBLOB */, 0, bytes, ref size);
if (!check)
{
throw new Win32Exception();
}
// The next lines could be optimized by using a CryptDecrypt
// that accepts a IntPtr and adding directly 12 to the ref bytes
// instead of copying around the byte array
// 12 == sizeof(BLOBHEADER) + sizeof(ALG_ID)
var bytes2 = new byte[size - 12];
Array.Copy(bytes, 12, bytes2, 0, bytes2.Length);
bytes = bytes2;
bytes2 = null;
check = Win32.CryptDecrypt(hExpKey, IntPtr.Zero, true, 0, bytes, ref size);
if (!check)
{
throw new Win32Exception();
}
Array.Resize(ref bytes, size);
return bytes;
}
finally
{
if (hExpKey != IntPtr.Zero)
{
Win32.CryptDestroyKey(hExpKey);
}
}
}
/// <summary>
/// WinAPI Imports
/// </summary>
internal class Win32
{
public const uint PROV_RSA_FULL = 1;
public const uint NTE_BAD_KEYSET = 0x80090016;
public const uint CRYPT_NEWKEYSET = 0x00000008;
public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
public const uint CRYPT_MACHINE_KEYSET = 0x00000020;
public const uint CRYPT_EXPORTABLE = 1;
public const uint ALG_CLASS_HASH = (4 << 13);
public const uint ALG_SID_MD5 = 3;
public const uint CALG_MD5 = (ALG_CLASS_HASH | ALG_SID_MD5);
public const uint ALG_CLASS_DATA_ENCRYPT = (3 << 13);
public const uint ALG_TYPE_BLOCK = (3 << 9);
public const uint ALG_SID_3DES = 3;
public const uint CALG_3DES = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_3DES);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptAcquireContext(out IntPtr hProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptCreateHash(IntPtr hProv, uint Algid, IntPtr hKey, uint dwFlags, out IntPtr hHash);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptHashData(IntPtr hHash, [In, Out] byte[] pbData, int dwDataLen, uint dwSize);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDeriveKey(IntPtr hProv, uint Algid, IntPtr hHash, uint dwFlags, out IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptGenKey(IntPtr hProv, uint Algid, uint dwFlags, out IntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, int final, uint dwFlags, [In, Out] byte[] pbData, ref int pdwDataLen, int dwBufLen);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptExportKey(IntPtr hKey, IntPtr hExpKey, uint dwBlobType, uint dwFlags, [Out] byte[] pbData, ref int pdwDataLen);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptGetKeyParam(IntPtr hKey, uint dwParam, [Out] byte[] pbData, ref int pdwDataLen, uint dwFlags);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, bool final, uint dwFlags, [In, Out] byte[] pbData, ref int pdwDataLen);
}