Rijndael加密器:获取空字节[]。不加密任何东西

时间:2019-06-10 00:53:11

标签: c# encryption aes rijndael

晚上好!

我正在尝试在C#中使用Rijndael算法和Rijndael类实现加密器。我试图遵循(没有做完全相同的代码)下面的链接,但是问题是给了一个要加密的字符串,但没有得到任何结果。我也没有收到任何错误消息。

https://docs.microsoft.com/pt-br/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8

CryptDecrypt.cs

CIM_DATETIME

Menu.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace RijndaelAlgorithm {
    public class CryptDecrypt {
        private Byte[] iv;
        private Byte[] key; 

        public CryptDecrypt(String key) {
            iv = new Byte[] {21, 10, 21, 251, 132, 76, 121, 27, 210, 81, 215, 99, 14, 235, 11, 75};
            this.key = Encoding.ASCII.GetBytes(key);
        }

        public String encryptMsg(String originalMsg) {
            byte[] encryptedMsg;

            Rijndael rijAlg = Rijndael.Create();
            rijAlg.Key = formatKey();
            rijAlg.IV = iv;

            MemoryStream msEncrypt = new MemoryStream();
            ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
            CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

            StreamWriter swEncrypt = new StreamWriter(csEncrypt);
            swEncrypt.Write(originalMsg);

            encryptedMsg = msEncrypt.ToArray();
            Console.WriteLine("encryptedMsg.Length: " + encryptedMsg.Length);

            return Convert.ToBase64String(encryptedMsg, 0, encryptedMsg.Length);
        }

        private Byte[] formatKey() {
            int len = key.Length;

            String strKey = System.Text.Encoding.UTF8.GetString(key);
            String fillKey = "";
            String strFormatedKey = "";

            Byte[] formatedKeyByte;

            if (len < 16)
                fillKey = new String('X',(16 - len));

            strFormatedKey = String.Concat(strKey, fillKey);
            formatedKeyByte = Encoding.ASCII.GetBytes(strFormatedKey);

            return formatedKeyByte;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您似乎想用.NET应用程序对消息进行加密,并希望获得与您在评论中提到的特定在线服务相同的加密字节。

参数

用于加密的一个参数是初始化向量(IV)。它应该是随机的,并且只能使用一次。因此,如果正确实现了两个应用程序(具有不同的随机IV),则加密的字节将不同。

即使您使用相同的输入,每次按下该键,该服务也会返回不同的结果。

但是,如果通常采用不同的加密结果并使用相同的密钥解密,则将获得原始字节。

使用此特定服务进行测试的下一个问题是,它们始终提供相同的前缀base64序列'U2FsdGVkX1'。这不是标准的AES输出(如果解码此base64序列,则会得到“ Salted_P”)。因此,使用其他在线服务进行测试很有意义。

因此,如果两个AES-256编码实现使用相同的参数,我们将获得相同的编码结果。我们需要它:

  • 密钥(32个字节,对于AES-256,不是16个字节)
  • IV(16个字节)

谈到密钥长度:正如评论中提到的其他内容一样,您不应该简单地添加“ X”或类似的东西,而应使用标准的加密机制来得出一个好的密钥。

方便进行测试的方法是将十六进制字符串转换为字节数组然后返回的方法,例如在这个很酷的答案中,请参见StringToByteArray和ByteArrayToString方法: https://stackoverflow.com/a/311179

让我们尝试一下。如果我们采用十六进制字符串“ 69736a7573746174657657374”作为消息“ isjustatest”,则需要一个32字节的AES-256密钥和16个字节的IV。

正如评论中其他人提到的那样,您需要刷新并关闭流(或者更好的是使用“ using”语句)。

获取代码并更改密钥和iv分配,并将加密的消息输出到控制台:

rijAlg.Key = StringToByteArray("519C7C3402A943D8AF83746C1548E475319EBDA6A38046059F83B21709BD6A5B"); //32 bytes
rijAlg.IV =  StringToByteArray("0D024CF947CE4C288880D0B34D29BFA5"); // 16 bytes
...
swEncrypt.Write(originalMsg);
swEncrypt.Flush();
swEncrypt.Close();
...
Console.WriteLine("encrypted bytes: '" + ByteArrayToString(encryptedMsg) + "'");

这将导致调试控制台中输出“ 419536f27da3406625b2d07f43833aab”。

所以现在我们可以使用在线服务,例如https://cryptii.com/pipes/aes-encryption,我们可以在其中输入输入数据,选择加密算法,提供密钥和IV字节,然后得到与您程序相同的结果,请参见此处的屏幕截图:

enter image description here

如上所述,在实际应用中使用它时,请不要忘记使用不同的随机IV。