简体   繁体   English

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

[英]Error in C# encrypt code when decrypting!

A bit more background info as suggested: I'm finsihing of an Intranet CMS web app where I have to use the products API (ASP.NET based). 如建议的更多背景信息:我正在使用一个Intranet CMS Web应用程序,必须使用产品API(基于ASP.NET)。 Because of time constraints and issues with Windows authen' I need another way to ensure staff do not need to re login everytime they visit the site to view personalised content. 由于时间限制和Windows身份验证的问题,我需要另一种方式来确保员工每次访问该网站以查看个性化内容时都无需重新登录。 The way it works is that once a user logs in (username/password), a Session ID storing a new different Security context value is generated that is used to display the personalised content. 它的工作方式是,一旦用户登录(用户名/密码),便会生成存储新的不同Security上下文值的会话ID,该会话ID用于显示个性化内容。 The API login method called uses the username and password as parameters. 调用的API登录方法使用用户名和密码作为参数。 The only way I can think of automatically logging in the next time the staff visits the site is by storing the password in a enrypted cookie and checking of its existing when the site is visited and then calling the API login method using the username and decrypted password cookie values. 我可以想到的唯一方法是,在下一次工作人员访问网站时自动登录,方法是将密码存储在加密的cookie中,并在访问该网站时检查其是否存在,然后使用用户名和解密的密码调用API登录方法Cookie值。

Any other ideas as an alternative welcomed. 任何其他想法作为替代。

Mo

Hi, I'm using some code found on the web to encrypt and decrypt a password string. 嗨,我使用网上找到的一些代码来加密和解密密码字符串。 It encrypts fine but when it calls the code below to decrypt the string it throws the error " Length of the data to decrypt is invalid " How can I resolve this? 它可以很好地加密,但是当它调用下面的代码来解密字符串时,会引发错误“ 要解密的数据长度无效 ”,我该如何解决?

Thanks in advance. 提前致谢。

Mo

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);

A couple of things here... 这里有几件事...

  1. You shouldn't encrypt passwords usually. 您通常不应加密密码。 You should hash them. 您应该对它们进行哈希处理

If you decide to continue down the road of encryption.. 如果您决定继续加密之路。

  1. You are using the DES algorithm. 您正在使用DES算法。 This is considered insecure and flawed. 这被认为是不安全和有缺陷的。 I'd recommend looking at the AES algorithm. 我建议看一下AES算法。
  2. Depending on how much data you are working with, the CryptoStream might be overkill. 根据要使用的数据量, CryptoStream可能会过大。
  3. Using the ASCII encoding can cause loss of data that isn't ASCII, like Cyrillic letters. 使用ASCII编码可能会导致非ASCII数据丢失,例如西里尔字母。 The recommended fix is to use something else, like UTF8. 推荐的修复方法是使用其他工具,例如UTF8。

Here is an example: 这是一个例子:

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);
}

This will use a random key every time. 每次将使用随机密钥。 It is likely that you will need to encrypt some data, then decrypt it at a later time. 您可能需要加密一些数据,然后在以后解密。 When you create the AesManaged object, you can store the Key and IV property. 创建AesManaged对象时,可以存储KeyIV属性。 You can re-use the same Key if you'd like, but different data should always be encrypted with a different IV (Initialization Vector). 您可以根据需要重复使用同一密钥,但始终应使用不同的IV(初始化向量)对不同的数据进行加密。 Where you store that key, is up to you. 存储密钥的位置取决于您。 That's why hashing might be a better alternative: there is no key, and no need to worry about storing the key safely. 这就是为什么散列可能是更好的选择的原因:没有密钥,也不必担心安全地存储密钥。

If you want to go down the hashing route, here is a small example: 如果您想沿哈希路径走,这是一个小例子:

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);
}

This uses the SHA1 algorithm, which should work fine for passwords, however you may want to consider SHA256 . 这使用SHA1算法,该算法应该可以很好地用于密码,但是您可能需要考虑SHA256

The concept is simple: a hash will produce a (mostly) unique output for an input, however the output cannot be converted back to the input - it's destructive. 这个概念很简单:哈希将为输入产生一个(大部分)唯一的输出,但是该输出不能转换回输入,这是破坏性的。 Whenever you want to check if a user should be authenticated, check hash the password they gave you, and check it against the hash of the correct password. 每当您想检查用户是否应该通过身份验证时,请检查用户给您的密码的哈希值,并对照正确密码的哈希值进行检查。 That way you aren't storing anything sensitive. 这样,您就不会存储任何敏感内容。

I've actually had this error before and it took me 3 days to figure out the solution. 实际上,我之前曾遇到过此错误,并且花了3天的时间才弄清楚解决方案。 The issue will be the fact that the machine key you need for descryption needs to be registered on your machine itself. 问题在于,解密所需的机器密钥需要在机器本身上注册。

Read fully up on DES encryption, it works by an application key, and a machine-level key. 充分阅读DES加密,它由一个应用程序密钥和一个计算机级密钥组成。 The error you're getting is likely because of the machine key missing. 您收到的错误很可能是由于缺少机器密钥。

Compare the bytes used to create the _pword string (in the encryption method) to the bytes retrieved with GetBytes. 将用于创建_pword字符串(在加密方法中)的字节与使用GetBytes检索的字节进行比较。 Probably you will notice a change in the data there. 可能您会注意到那里的数据发生了变化。

To store the encrypted bytes, I think you should use Convert.ToBase64String and Convert.FromBase64String turn the encrypted password to/from a string. 要存储加密的字节,我认为您应该使用Convert.ToBase64String和Convert.FromBase64String将加密的密码转为字符串。

I also do not see the code where you set the Key and IV. 我也看不到设置Key和IV的代码。 So I guess you are using a different key to encrypt and decrypt the password. 因此,我想您正在使用其他密钥来加密和解密密码。

If the current Key property is null, the GenerateKey method is called to create a new random Key. 如果当前Key属性为null,则调用GenerateKey方法创建一个新的随机Key。 If the current IV property is null, the GenerateIV method is called to create a new random IV. 如果当前IV属性为null,则调用GenerateIV方法以创建新的随机IV。

DES is a block based cipher - only certain lengths of buffers are valid. DES是基于块的密码-只有特定长度的缓冲区有效。 If I remember correctly, the block size for DES is 64 bits, so you need to ensure that your byte array is a multiple of 8 bytes long. 如果我没记错的话,DES的块大小是64位,因此您需要确保字节数组的长度是8个字节的倍数。

(That should fix your immediate problem, but I'd reference other peoples advice here - you really ought not to be using DES for any new code, and for passwords it's usually more appropriate to hash than to encrypt). (这应该可以解决您眼前的问题,但是我在这里参考其他人的建议-您真的不应该在任何新代码中使用DES,对于密码来说,通常更适合使用散列而不是加密)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM