解密时C#加密代码出错!

时间:2011-03-31 11:50:54

标签: c# asp.net string encryption

建议的更多背景信息: 我正在使用Intranet CMS Web应用程序,我必须使用产品API(基于ASP.NET)。由于时间限制和Windows authen的问题'我需要另一种方法来确保员工每次访问网站时都不需要重新登录以查看个性化内容。它的工作方式是,一旦用户登录(用户名/密码),就会生成一个存储新的不同安全上下文值的会话ID,用于显示个性化内容。调用的API登录方法使用用户名和密码作为参数。我可以想到下次工作人员访问网站时自动登录的唯一方法是将密码存储在加密的cookie中,并在访问网站时检查其存在,然后使用用户名和解密密码调用API登录方法饼干值。

欢迎任何其他想法作为替代方案。

您好, 我正在使用Web上的一些代码来加密和解密密码字符串。它加密很好但是当它调用下面的代码来解密字符串时它会抛出错误“要解密的数据的长度无效”我该如何解决这个问题?

提前致谢。

System.Text.Encoding enc = System.Text.Encoding.ASCII;
            byte[] myByteArray = enc.GetBytes(_pword);


            SymmetricAlgorithm sa = DES.Create();
            MemoryStream msDecrypt = new MemoryStream(myByteArray);
            CryptoStream csDecrypt = new CryptoStream(msDecrypt, sa.CreateDecryptor(), CryptoStreamMode.Read);
            byte[] decryptedTextBytes = new Byte[myByteArray.Length];
            csDecrypt.Read(decryptedTextBytes, 0, myByteArray.Length);
            csDecrypt.Close();
            msDecrypt.Close();

            string decryptedTextString = (new UnicodeEncoding()).GetString(decryptedTextBytes);

4 个答案:

答案 0 :(得分:3)

这里有几件事......

  1. 您通常不应加密密码。你应该hash他们。
  2. 如果您决定继续加密......

    1. 您正在使用DES算法。这被认为是不安全和有缺陷的。我建议看一下AES算法。
    2. 根据您使用的数据量,CryptoStream可能过度。
    3. 使用ASCII编码会导致丢失非ASCII的数据,如西里尔字母。推荐的修复方法是使用其他东西,例如UTF8。
    4. 以下是一个例子:

      string text = "Hello";
      using (var aes = new AesManaged())
      {
          var bytes = System.Text.Encoding.UTF8.GetBytes(text);
          byte[] encryptedBytes;
          using (var encrypt = aes.CreateEncryptor())
          {
              encryptedBytes = encrypt.TransformFinalBlock(bytes, 0, bytes.Length);
          }
          byte[] decryptedBytes;
          using (var decrypt = aes.CreateDecryptor())
          {
              decryptedBytes = decrypt.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
          }
          var decryptedText = System.Text.Encoding.UTF8.GetString(decryptedBytes);
          Console.Out.WriteLine("decryptedText = {0}", decryptedText);
      }
      

      每次都会使用随机密钥。您可能需要加密某些数据,然后在以后解密。创建AesManaged对象时,可以存储KeyIV属性。如果您愿意,可以重复使用相同的密钥,但应始终使用不同的IV(初始化向量)加密不同的数据。存储该密钥的位置取决于您。这就是为什么散列可能是一个更好的选择:没有密钥,也不必担心安全地存储密钥。

      如果你想沿着哈希路线走下去,这里有一个小例子:

      var textToHash = "hello";
      using (SHA1 sha = new SHA1Managed())
      {
          var bytesToHash = System.Text.Encoding.UTF8.GetBytes(textToHash);
          var hash = sha.ComputeHash(bytesToHash);
          string base64hash = Convert.ToBase64String(hash);
      }
      

      这使用SHA1算法,该算法适用于密码,但您可能需要考虑SHA256

      概念很简单:哈希将为输入生成(大部分)唯一输出,但输出无法转换回输入 - 它具有破坏性。每当您想要检查用户是否应该进行身份验证时,请检查哈希给他们的密码,并根据正确密码的哈希值进行检查。这样你就不会存储任何敏感信息。

答案 1 :(得分:0)

之前我确实遇到过这个错误,花了3天的时间才找出解决方案。问题在于,需要用于解密的机器密钥需要在您的机器上注册。

完全阅读DES加密,它通过应用程序密钥和机器级密钥工作。您得到的错误可能是因为缺少机器密钥。

答案 2 :(得分:0)

将用于创建_pword字符串的字节(在加密方法中)与使用GetBytes检索的字节进行比较。可能你会注意到那里数据的变化。

要存储加密的字节,我认为你应该使用Convert.ToBase64String和Convert.FromBase64String将加密的密码转换成字符串。

我也没有看到设置Key和IV的代码。所以我猜你使用不同的密钥来加密和解密密码。

  

如果当前Key属性为null,   调用GenerateKey方法   创建一个新的随机密钥。如果   当前的IV属性为null   调用GenerateIV方法来创建   一个新的随机IV。

答案 3 :(得分:0)

DES是基于块的密码 - 只有某些长度的缓冲区有效。如果我没记错的话,DES的块大小是64位,所以你需要确保你的字节数组是8字节长的倍数。

(这应该可以解决你的问题,但我会在这里引用其他人的建议 - 你真的不应该使用DES来代替任何新代码,而对于密码来说,散列通常比加密更合适。)