【问题标题】:Rijndael cryptography encryptionRijndael 密码学加密
【发布时间】:2017-06-26 13:19:00
【问题描述】:

我有使用 C# .NET Rijndael 加密的示例代码,它可以解密密文“FGgsUwQ1gToX40dfgdfgfdgdfgdfCzEr3wOenxTPMN9jJC”到普通的“75.117.87.87”。

enter image description here

我已经尝试写加密纯文本“75.117.87.87”到“FGgsUwQ1gToX40dfgdfgfdgdfgdfCzEr3wOenxTPMN9jJC”的保留方法但没有成功(加密文本与预期不一样 - ,但结果喜欢附图。请帮帮我,谢谢。

static int Main(string[] args)
    {
        Decrypt();
        Console.WriteLine("########################");
        Console.WriteLine("########################");
        Encrypt();
        Console.ReadLine();
        return 0;
    }
public static void Decrypt()
    {
        string ciphertext = "LkbsUwQ1gToX40dYXizgc0BCCCzEr3wOenxTPMN9jJC";
        string secretkey = "11111111";
        string saltkey = "thekey";

        string result =  rijndaelDecrypt(ciphertext, secretkey, saltkey);

        Console.WriteLine("Cipher text: " + ciphertext);
        Console.WriteLine("Decrypted text: " + result);
        return;
    }
public static string  rijndaelDecrypt(string ciphertext, string secretkey, string saltkey)
    {
        if (string.IsNullOrEmpty(ciphertext))
        {
            return null;
        }
        if (string.IsNullOrEmpty(secretkey))
        {
            return null;
        }

        ciphertext = "EAAAA" + ciphertext;

        RijndaelManaged rijndaelManaged = null;
        string result = null;
        try
        {
            Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(secretkey, Encoding.ASCII.GetBytes(saltkey));
            byte[] buffer = Convert.FromBase64String(ciphertext);
            MemoryStream memoryStream = new MemoryStream(buffer);
            rijndaelManaged = new RijndaelManaged();
            rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
            rijndaelManaged.IV = rb(memoryStream);
            ICryptoTransform transform = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read);
            StreamReader streamReader = new StreamReader(cryptoStream);
            result = streamReader.ReadToEnd();
        }
        catch (Exception)
        {
            if (rijndaelManaged != null)
            {
                rijndaelManaged.Clear();
            }
            return null;
        }
        finally
        {
            if (rijndaelManaged != null)
            {
                rijndaelManaged.Clear();
            }
        }
        return result;
    }
public static void Encrypt()
    {
        string ciphertext = "75.117.87.87";
        string secretkey = "1111111";
        string saltkey = "thekey";
        string result;
        RijndaelManaged rijndaelManaged = new RijndaelManaged();

        Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(secretkey, Encoding.ASCII.GetBytes(saltkey));

        rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);

        byte[] buffer = EncodeToBytes(ciphertext);
        MemoryStream memoryStream = new MemoryStream(buffer);
        rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
        //rijndaelManaged.IV = rb(memoryStream);

        ICryptoTransform transform = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
        CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read);
        StreamReader streamReader = new StreamReader(cryptoStream);
        result = streamReader.ReadToEnd();


        var encryptor = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
        var msEncrypt = new MemoryStream();

        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        using (var swEncrypt = new StreamWriter(csEncrypt))
            swEncrypt.Write(result);

        result = Convert.ToBase64String(msEncrypt.ToArray());

        Console.WriteLine("Plain text: " + ciphertext);
        Console.WriteLine("Encrypted text: " + result);
        return;
    }
private static byte[] rb(Stream s)
    {
        byte[] array = new byte[4];
        if (s.Read(array, 0, array.Length) != array.Length)
        {
            return null;
        }
        byte[] array2 = new byte[BitConverter.ToInt32(array, 0)];
        if (s.Read(array2, 0, array2.Length) != array2.Length)
        {
            return null;
        }
        return array2;
    }
 private static byte[] EncodeToBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

【问题讨论】:

  • 我在您的代码中没有看到任何试验 :)
  • 我没有看到任何加密方法的尝试。当问“为什么 X 不工作?”时确保至少显示 X 的代码。当你解释你尝试了什么时会更好。
  • @domi1819 : 我更新了加密方法和图片,感谢您的关注!我认为问题是加密方法中的初始化向量

标签: c# encryption cryptography rijndael


【解决方案1】:

您正在使用不同的 IV。对于您的解密方法,您使用的是 base64 解码的密文:

byte[] buffer = Convert.FromBase64String(ciphertext);
MemoryStream memoryStream = new MemoryStream(buffer);
rijndaelManaged.IV = rb(memoryStream);

对于您的加密方法,您使用 PBKDF2 (Rfc2898DeriveBytes) 从密码中派生它,当且仅当您使用随机盐构造 Rfc2898DeriveBytes 时,这是正确的方法。 或者,您可以使用 RNGCryptoServiceProvider 获得完全随机的 IV。

rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);

从安全角度来看,您应该使用随机盐来派生您的密钥/IV,并在加密时将其添加到密文中。对于解密,您应该再次将其切断(并将其用于派生解密密钥/IV)。

【讨论】:

  • 我投了反对票,因为从 KDF 派生 IV 不是您应该做的事情,因为在同一密钥下加密时您最终会得到一个静态 IV。 IV 应始终使用 CSPRNG 随机生成。
  • @LukePark 如果可以的话,我会否决您的评论,因为在使用随机盐时,从 KDF 派生 IV 是很好的。 (这就是为什么我提出关于随机盐的安全建议,你应该总是这样做)
  • 我想你误会了。我并不是说生成的 IV 不合适。我反对您的一揽子声明“对于您的加密算法,您是从密码中得出的……这是正确的做法。”。这不是正确的做法,而且具有误导性。在这种情况下,在这些特定情况下,它会产生可接受的结果。但是,更改代码以重新使用 AES 实例会立即引入问题。如果代码只是每次随机生成IV,就不可能通过更改其他区域的代码来引入错误。
  • 更具体地说,请记住 StackOverflow 的目的是帮助他人,就像帮助 OP 一样。如果不太精通密码学的人阅读您关于从与密钥相同的 KDF 派生 IV 的建议怎么办?非常误导。希望你能理解。
  • @domi1819 只需使用 CSPRNG 即可获得 IV。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 2012-07-20
相关资源
最近更新 更多