Мне поручено заменить старый код, используя устаревший CryptoApi, новым API-интерфейсом Cryptography: Next Generation из окон.Новый метод шифрования должен давать тот же результат, что и старый.
Я упростил старые методы, чтобы сделать его более компактным (вы можете просмотреть его как псевдокод):
private UIntPtr mProviderHandle = UIntPtr.Zero;
private UIntPtr mHashHandle = UIntPtr.Zero;
private UIntPtr mKeyHandle = UIntPtr.Zero;
private uint mBlockSize = 0;
private bool m_disposed;
private void Init(string pContextName, string pSharedSecret)
{
string providerName = = "Microsoft Base Cryptographic Provider v1.0";
var providerType = ProviderType.PROV_RSA_FULL; // 1
var providerFlags = ContextOperations.CRYPT_DEFAULT; // 0
var hashAlg = ProviderAlgorithm.CALG_MD5; // 0x8003
var keyAlg = ProviderAlgorithm.CALG_RC2; // 0x6602
CryptAcquireContext(ref mProviderHandle, pContextName, providerName, providerType, providerFlags);
CryptCreateHash(mProviderHandle, hashAlg, UIntPtr.Zero, 0, ref mHashHandle);
CryptHashData(mHashHandle, Encoding.Default.GetBytes(pSharedSecret), (uint)pSharedSecret.Length, 0))
CryptDeriveKey(mProviderHandle, keyAlg, mHashHandle, 0, ref mKeyHandle));
}
public byte[] Encrypt(byte[] pData, bool pFinal = true)
{
uint length = (uint)bytes.Length;
uint m = 0;
if (0 < BlockSize)
{
// one more blocks than the number of blocks touched
m = (uint)(((((length - 1) / BlockSize) + 1) + 1) * BlockSize);
Array.Resize(ref bytes, (int)m);
}
else
{
m = length;
}
APIBOOL apiFinal = pFinal ? APIBOOL.TRUE : APIBOOL.FALSE;
if (APIBOOL.FALSE != NativeMethods.CryptEncrypt(mKeyHandle, UIntPtr.Zero, apiFinal, 0,
bytes, ref length, m))
{
Array.Resize(ref bytes, (int)length);
encrypted = true;
}
return bytes;
}
Ивот новый метод:
private byte[] EncryptCNG(byte[] data, string pSharedSecret)
{
using (RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider())
{
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
rc2.Key = md5.ComputeHash(Encoding.Unicode.GetBytes(pSharedSecret));
rc2.IV = new byte[rc2.BlockSize/8];
}
var encryptor = rc2.CreateEncryptor();
var result = encryptor.TransformFinalBlock(data, 0, data.Length);
return result;
}
}
Оба метода Encrypt () и EncryptCNG () создают байтовый массив с одинаковой длиной и постоянным значением (в зависимости от входных данных).Но значения / байты различаются.Желаемый результат заключается в том, что один и тот же вход генерирует идентичный выход.Так что Encrypt может быть заменен EncryptCNG.Мои вопросы: является ли EncryptCNG правильным способом использования нового API и является ли это правильным переводом функциональности Init + Encrypt?И если да, то почему он дает разные результаты?
Любая помощь очень ценится.