c# - 如何复制此在线工具使用的 AES 加密

标签 c# encryption aes

http://aes.online-domain-tools.com/

我正在尝试使用 CBC 通过 C# 复制此加密,但无论我如何尝试都没有得到相同的结果。

到目前为止我的代码:

    private byte[] hex2bytes(string s)
    {
        return Enumerable.Range(0, s.Length)
                         .Where(x => x % 2 == 0)
                         .Select(x => Convert.ToByte(s.Substring(x, 2), 16))
                         .ToArray();        
    }

private AesCryptoServiceProvider GetProvider(byte[] key)
{
    AesCryptoServiceProvider result = new AesCryptoServiceProvider();
    result.BlockSize = 128;
    result.KeySize = 128;
    result.Mode = CipherMode.CBC;
    result.Padding = PaddingMode.PKCS7;

    result.GenerateIV();
    //result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    result.IV = hex2bytes("ad77d666311839f5665aeb2e42f64542");

    byte[] RealKey = GetKey(key, result);
    _key = Encoding.ASCII.GetString(RealKey);
    result.Key = RealKey;
    // result.IV = RealKey;
    return result;
}

private byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
{
    byte[] kRaw = suggestedKey;
    List<byte> kList = new List<byte>();

    for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8)
    {
        kList.Add(kRaw[(i / 8) % kRaw.Length]);
    }
    byte[] k = kList.ToArray();
    return k;
}

/// <summary>
/// Encrpyts the sourceString, returns this result as an Aes encrpyted, BASE64 encoded string
/// </summary>
/// <param name="plainSourceStringToEncrypt">a plain, Framework string (ASCII, null terminated)</param>
/// <param name="passPhrase">The pass phrase.</param>
/// <returns>
/// returns an Aes encrypted, BASE64 encoded string
/// </returns>
public string EncryptString(string plainSourceStringToEncrypt, string passPhrase)
{
    //Set up the encryption objects
    using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(passPhrase)))
    {
        byte[] sourceBytes = Encoding.UTF8.GetBytes(plainSourceStringToEncrypt);
        ICryptoTransform ictE = acsp.CreateEncryptor();

        //Set up stream to contain the encryption
        MemoryStream msS = new MemoryStream();

        //Perform the encrpytion, storing output into the stream
        CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write);
        csS.Write(sourceBytes, 0, sourceBytes.Length);
        csS.FlushFinalBlock();

        //sourceBytes are now encrypted as an array of secure bytes
        byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer
        var x = BitConverter.ToString(encryptedBytes);
        //return the encrypted bytes as a BASE64 encoded string
        return Convert.ToBase64String(encryptedBytes);
    }
}


/// <summary>
/// Decrypts a BASE64 encoded string of encrypted data, returns a plain string
/// </summary>
/// <param name="base64StringToDecrypt">an Aes encrypted AND base64 encoded string</param>
/// <param name="passphrase">The passphrase.</param>
/// <returns>returns a plain string</returns>
public string DecryptString(string base64StringToDecrypt, string passphrase)
{
    //Set up the encryption objects
    using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(passphrase)))
    {
        byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
        ICryptoTransform ictD = acsp.CreateDecryptor();

        //RawBytes now contains original byte array, still in Encrypted state

        //Decrypt into stream
        MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
        CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
        //csD now contains original byte array, fully decrypted

        //return the content of msD as a regular string
        return (new StreamReader(csD)).ReadToEnd();
    }
}

最佳答案

好的,所以根据描述, key 是用零字节填充的。您实际上是在重复关键字节。这两种方法当然都是完全不安全的, key 应该只包含随机字节。

IV 似乎是在填充 key 字节之前使用 SHA-1 计算的。我在你的代码中没有看到任何相关内容。请注意,每次使用相同的 key 时,IV 都应该更改,因此在 key 上使用 SHA-1 是不安全的。

填充是零填充,最多可达 block 的大小。这意味着如果您的明文以 00 字节结尾,您将丢失数据。没有提到填充,但我通过加密某些内容然后使用相同的 key 对其进行解密来测试了这一点。看来填充字节仍然存在。这并不是不安全,但由于它可能会导致无效的明文,因此肯定是错误的。

没有添加身份验证标签(例如 HMAC),这意味着任何人都可以更改密文并逃脱惩罚。在最好的情况下,这只会导致其他系统上出现垃圾。在最坏的情况下(这是最有可能的),您也将完全失去保密性。这可能就是您首先想要实现的目标。

我希望我已经为您提供了足够的指导来创建实现 - 出于学习目的或从给定的代码迁移。如果您使用来自互联网的随机垃圾(没有别的词可以形容这一点),那么您最终的安全性将为零。我不会提供代码,因为我不希望这种情况激增。

关于c# - 如何复制此在线工具使用的 AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24080630/

相关文章:

java - 如何验证GMAC?

java - AES 加密的 88 字节输出

c# - 使用参数的 Prism 命令绑定(bind)?

php - 不使用HTTPS登录,如何安全?

mysql - 将方法名称绑定(bind)到 mysql where 子句?

c++ - 汇编asm x86加解密程序

c - Libgcrypt 中的 AES CCM 加密和解密

c# - 创建模拟时如何组合两个接口(interface)?

c# - 跨AppDomains的NLog配置

c# - 如何使用按钮事件在 C# 中切换表单