Как перевести CryptoApi в API криптографии: следующее поколение - PullRequest
0 голосов
/ 09 июля 2019

Мне поручено заменить старый код, используя устаревший 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?И если да, то почему он дает разные результаты?

Любая помощь очень ценится.

...