【问题标题】:C# Rijndael Encryption not accepting any Key except "mykey123"C# Rijndael 加密不接受除“mykey123”之外的任何密钥
【发布时间】:2015-12-15 20:59:24
【问题描述】:

我在http://www.codeproject.com/Articles/26085/File-Encryption-and-Decryption-in-C 上找到了这个脚本。当我使用静态键// string password = @"myKey1234"; // Your Key Here 时它工作正常。当我传入不同的密钥时,它不起作用string password = @keyPwd;。您可以在我的代码中看到我正在传递密钥以使其不起作用。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace CSVEncrypts
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string inputFile = "";
        string outputFilePath = "";
        string oFilePathName = "";

// EncryptFile
        private void EncryptFile(string inputFile, string outputFile,string keyPwd )
        {
            try
            {
               // string password = @"myKey123"; // Your Key Here
                string password = @keyPwd; 
                UnicodeEncoding UE = new UnicodeEncoding();
                byte[] key = UE.GetBytes(password);
                string cryptFile = outputFile;
                FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
                RijndaelManaged RMCrypto = new RijndaelManaged();

                CryptoStream cs = new CryptoStream(fsCrypt,RMCrypto.CreateEncryptor(key, key),CryptoStreamMode.Write);
                FileStream fsIn = new FileStream(inputFile, FileMode.Open);
                int data;
                while ((data = fsIn.ReadByte()) != -1)
                    cs.WriteByte((byte)data);
                fsIn.Close();
                cs.Close();
                fsCrypt.Close();
            }
            catch
            {
                MessageBox.Show("Encryption failed!", "Error");
            }
        }


// Decrypt
        private void DecryptFile(string inputFile, string outputFile, string keyPwd)
        {
            {
                //string password = @"myKey123"; // Your Key Here
                string password = @keyPwd; // Your Key Here
                UnicodeEncoding UE = new UnicodeEncoding();
                byte[] key = UE.GetBytes(password);
                FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
                RijndaelManaged RMCrypto = new RijndaelManaged();
                CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateDecryptor(key, key),CryptoStreamMode.Read);

                FileStream fsOut = new FileStream(outputFile, FileMode.Create);
                int data;
                while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);
                fsOut.Close();
                cs.Close();
                fsCrypt.Close();
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {

           if (inputFile != "")
            {
                oFilePathName = outputFilePath + "\\" + textBox1.Text;
                EncryptFile(inputFile, oFilePathName,keytextBox.Text);
            }
        }



        private void button2_Click(object sender, EventArgs e)
        {

            if (inputFile != "") ;
            {
                oFilePathName = outputFilePath + "\\" + textBox1.Text;
              DecryptFile(inputFile, oFilePathName, keytextBox.Text);
            }
        }



        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog InputOpenFileDialog1 = new OpenFileDialog();
            if (InputOpenFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string strInfilename = InputOpenFileDialog1.FileName;
                button3.Text = strInfilename;
                inputFile = strInfilename;
                outputFilePath = Path.GetDirectoryName(inputFile);
            }
        }


    }

}

【问题讨论】:

  • 对称加密算法具有预定义的密钥大小。尝试传入 8 个字符的字符串(64 位密钥),因为 myKey123 的长度为 8 个字符
  • Unicode 编码在这种情况下也很危险。如果您的密钥中有任何非 ASCII 字符,它将呈现为多个字节,这将导致另一个错误
  • 另外,有效密钥大小不限于64位,可以看details here

标签: c# encryption cryptography rijndael rijndaelmanaged


【解决方案1】:

密钥应该只包含与随机无法区分的位。编码为字节的密码不是密钥。特别是在使用Unicode 编码(应该命名为UTF16LE)时,许多位都设置为零。这意味着“密钥”也没有包含足够的熵。

要从密码创建密钥,您应该使用基于密码的密钥派生函数 (PBKDF) 派生它。在当前 .NET Crypto API 中执行此操作的最佳方法可能是使用实现 PBKDF2 的类 Rfc2898DeriveBytes。 PBKDF2 在RFC 2898: PKCS #5: Password-Based Cryptography Specification V2.0 中定义。如果您想做基于密码的加密,您可能需要阅读。

【讨论】:

    【解决方案2】:

    对于 Rijndael,我假设您的意思是 AES(高级加密标准),AES 是 Rijndael 的子集,块大小为 128 位,这正是您所需要的。

    AES 密钥是 128、192 或 256 位,最好不要使用字符串,如果您有字符串,请先通过 PBKDF2 等密钥派生函数运行它。键确实应该是字节数组,而不是字符串。使键的大小完全正确,这可能是您的问题。

    CreateDecryptor 有两个参数,key 和 iv,不要同时使用 iv 的 key,iv 被认为是公共的。

    从代码中看不清楚,你需要查阅文档以查看默认模式是否为 CBC 以及是否启用了 PKCS#7(PKCS#5 填充可互换使用)填充。

    如果您想要“开箱即用的安全加密”:使用RNCryptor,还有C# version。您还将获得多语言/平台互操作性。

    正确的加密安全并不容易,很容易犯一个破坏安全的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-20
      • 2016-05-26
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 2012-05-02
      相关资源
      最近更新 更多