首页 > 解决方案 > 将对象列表加密和解密为 byte[]

问题描述

当前解决方案

因此,我得到了一个可靠的 C# AES (Rijndael) 解密和加密方法,可以将字符串转换为字节数组 (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;
        }

解密方法(byte[]转string):

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<CustomObject> 加密为 byte[],然后才能将其从 byte[] 解密为 List<CustomObject>。请记住,CustomObject 是一个示例 / Foo 类。

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

我要转换的 List<CustomObject>:

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

这是 List<> 中的 CustomObject 类:

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

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

标签: c#encryptionserializationaes

解决方案


您先将其序列化为字符串然后加密如何。

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

将对象表示为字符串的一种格式是 JSON,并且从 dotnet core 3开始将序列化/反序列化为JSON 构建到 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>>(...);

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

其他序列化方法

使用 JSON 是首选(我),因为您作为人类也可以读取内部数据,而且它的字节数比 xml 少。您也可以考虑这些格式。

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

推荐阅读