Rijndael加密 - 只有字符串的一部分被解密

3

只有部分字符串被解密了,我认为这与我的编码有关。

以下是发生的情况:

        string s = "The brown fox jumped over the green frog";
        string k = "urieurut";
        string enc = EncryptString(s, k);
        string dec = DecryptString(enc, k);

这是翻译的结果:这就是结果:棕色的狐狸跳过了那只青蛙。
public static string EncryptString(string stringToEncrypt, string encryptionKey)
{
    string encrypted = String.Empty;

    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    byte[] encryptedString = UE.GetBytes(stringToEncrypt);
    cs.Write(encryptedString, 0, encryptedString.Length);
    cs.FlushFinalBlock();
    cs.Close();

    encrypted = UE.GetString(ms.ToArray());
    return encrypted;
}

public static string DecryptString(string stringToDecrypt, string encryptionKey)
{
    string decrypted = String.Empty;

    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);
    byte[] data = UE.GetBytes(stringToDecrypt);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    cs.Close();

    decrypted = UE.GetString(ms.ToArray());

    return decrypted;
}

哇,很酷!... 我在结果中看到破碎的韩语... - code4life
我开始怀疑朝鲜是否在攻击我的东西。 - schmoopy
3个回答

3

这里是你需要的内容:

    string s = "The brown fox jumped over the green frog";
    string k = "urieurut";
    byte[] enc = EncryptString(s, k);
    string dec = DecryptString(enc, k);

你不能尝试将加密的一堆字节解释为Unicode字符串。保持它们为字节。解密后的版本可以转换回字符串。

另外请注意下面的可处理对象的处置。如果您不使用using()Dispose()正确释放它们,可能会导致某些资源被持有太长时间或泄漏。

public static byte[] EncryptString(string stringToEncrypt, string encryptionKey)
{
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    using (RijndaelManaged RMCrypto = new RijndaelManaged())
    using (MemoryStream ms = new MemoryStream())
    using (ICryptoTransform encryptor = RMCrypto.CreateEncryptor(key, key))
    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
    {
        byte[] encryptedString = UE.GetBytes(stringToEncrypt);
        cs.Write(encryptedString, 0, encryptedString.Length);
        cs.FlushFinalBlock();
        return ms.ToArray();
    }
}

public static string DecryptString(byte[] stringToDecrypt, string encryptionKey)
{
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    using (RijndaelManaged RMCrypto = new RijndaelManaged())
    using (MemoryStream ms = new MemoryStream())
    using (ICryptoTransform decryptor = RMCrypto.CreateDecryptor(key, key))
    using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
    {
        cs.Write(stringToDecrypt, 0, stringToDecrypt.Length);
        cs.FlushFinalBlock();
        return UE.GetString(ms.ToArray());
    }
}

1
如果需要一个字符串,可以对其进行base64编码。 - GalacticCowboy
是的,我正在处理(大部分)对象,我只是为了清晰起见使用了示例 - 但我错过了一个未处理的对象,如果你没有指出来,我就不会发现 - 谢谢。 - schmoopy
好奇-为什么有人给这个点了踩?欢迎发表评论。 - Jesse C. Slicer

1

我通过使用base64字符串进行加密解决了我的问题 - 我可能会看其他选项,但我只需要这些方法来处理少量数据,这是最终代码:

public static string EncryptString(string stringToEncrypt, string encryptionKey)
{
    string encrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    byte[] encryptedString = Encoding.ASCII.GetBytes(stringToEncrypt);
    cs.Write(encryptedString, 0, encryptedString.Length);
    cs.FlushFinalBlock();
    cs.Close();

    //encrypted = Encoding.ASCII.GetString(ms.ToArray());
    return Convert.ToBase64String(ms.ToArray());
}

public static string DecryptString(string stringToDecrypt, string encryptionKey)
{
    string decrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);
    byte[] data = Convert.FromBase64String(stringToDecrypt);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    cs.Close();

    decrypted = Encoding.ASCII.GetString(ms.ToArray());

    return decrypted;
}

请注意,byte[] key = Encoding.Unicode.GetBytes(encryptionKey); 最多只会使用密码中的6个字符来形成一个相当弱的密钥。使用ASCII或UTF8已经是一个很大的改进了,要做到正确,请参考Rfc2898DeriveBytes类。 - H H
@Henk,你能解释一下为什么从Unicode字符串获取Unicode字符时最多只使用6个字符吗? - Jesse C. Slicer
哇,我从来不知道前16个字节是长度。感谢您提供的信息。 - Jesse C. Slicer
这里只是一个更正:UniCode.GetBytes()不使用长度前缀,这是我的错误。但是8个字符的密码将产生一个16字节的密钥,其中一半的字节为00。另请参见https://dev59.com/Rk7Sa4cB1Zd3GeqP21kw。 - H H
哎呀,又有人投了反对票,却没有解释。太棒了。 - Jesse C. Slicer

0

我不确定你具体的代码块,但Jeff Atwood之前写了一个很好用的小库:

http://www.codeproject.com/KB/security/SimpleEncryption.aspx

值得一看,因为它大大简化了加密过程,当我发现它时,我实际上不得不将其移植到 C#,因为当时没有可用的移植版本。但是现在评论部分有一个C#移植版本。

我会看一下,我喜欢那里的不同选项 - 谢谢。 - schmoopy
很酷,抱歉我不能直接帮助你。 - Adam Houldsworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接