将对象列表加密和解密到 byte[]

Encrypt and Decrypt a List of objects to byte[]

当前解决方案

所以,我得到了一种可靠的 C# AES ( Rijndael ) 解密和加密方法,可以将字符串转换为字节数组 ( byte[] )。

这非常有用,因为它允许我向网络发送和接收受对称加密保护的信息。

加密方法(string to byte[]):

private byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
        {
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;

            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            return encrypted;
        }

解密方法(字节[]转字符串):

private string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            string plaintext = null;

            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                try
                {
                    using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                    {
                        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                            {
                                plaintext = srDecrypt.ReadToEnd();
                            }
                        }
                    }
                }
                catch (Exception)    //if decription doesnt work, do normal conversion
                {
                    plaintext = Encoding.Unicode.GetString(cipherText);
                }
            }
            return plaintext;
        }

问题

现在需要通过网络发送和接收整个自定义对象列表,同时仍然使用 AES 加密。

我需要将整个 List 加密为 byte[],然后才能将其从 byte[] 解密为 List。请记住,CustomObject 是一个示例/Foo class.

但我不知道如何修改这些方法以使用我的 List 而不是字符串。到目前为止似乎没有任何效果...

我要转换的List

public List<CustomObject> ListCustomObjects = new List<CustomObject>();

这是 List<> 中的 CustomObject class:

public class CustomObject
    {
        public string NameFoo { get; set; }
        public float NumberFoo { get; set; }
        public bool ConditionFoo { get; set; }
    }

有什么解决办法吗?将对象列表转换为加密的字节数组并能够在需要时将其转换回列表对这个项目至关重要。

要不你先序列化成字符串再加密

然后在另一边,解密并反序列化

一种将对象表示为字符串的格式是 JSON,并且 serialize/deserialize 到 JSON 自 dotnet 核心 3 以来已内置到 dotnet 中。您也可以使用 Newtonsoft.JSON(它曾经是 c# 的默认 json 序列化器)

所以可以添加如下代码:

// using System.Text.Json;
// using System.Text.Json.Serialization;
private byte[] EncryptObjectToBytes<T>(T inputObject, byte[] Key, byte[] IV) {
  var jsonString = JsonSerializer.Serialize(inputObject);
  return EncryptStringToBytes(jsonString, Key, IV);
}

// and for the other side
private T DecryptObjectFromBytes<T>(byte[] cipherText, byte[] Key, byte[] IV) {
  var jsonString = DecryptStringFromBytes(cipherText, Key, IV);
  return JsonSerializer.Deserialize<T>(jsonString);
}

// Call the decryption like:
DecryptObjectFromBytes<YourClassName>(...);
// or for collections
DecryptObjectFromBytes<List<YourClassName>>(...);

您甚至可以优化上面的代码(因为您还可以(反)序列化到字节数组或从字节数组序列化,这将使它更快。您还可以使用异步 SerializeAsyncDeserializeAsync 方法,但这段代码应该可以帮助您入门。

其他序列化方式

(我)更喜欢使用 JSON,因为你作为一个人也可以读取内部数据,而且它的字节数比 xml 少。你也可以考虑这些格式。

  • MessagePack(由人类序列化为 none 可读字节数组)= 对于大对象来说更小。
  • XML 这是开发人员在发明 json 之前使用的东西。看起来像 html,但需要更多字符来序列化消息。