如何将CryptoApi转换为密码学API:下一代

时间:2019-07-09 10:03:24

标签: c# cryptoapi cng

我的任务是使用CryptoApi替换一些旧的旧代码,而CryptoApi已被弃用,并使用更新的Cryptography API:Windows的下一代。新的加密方法必须产生与旧的相同的结果。

我简化了旧方法以使其更紧凑(您可以将其视为伪代码):

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功能的正确翻译?如果是的话,为什么会产生不同的结果?

非常感谢您的帮助。

0 个答案:

没有答案