加密和解密字节数组

时间:2013-12-16 04:57:19

标签: c#

我有以下实用程序函数将我的对象序列化为加密字节数组,并从解密字节数组反序列化

//encryption key
public static byte[] Key = new byte[]{0x43, 0x72, 0x6e, 0x6d, 0x54, 0x4d, 0x65,
                                      0x94, 0x16, 0x32, 0x44, 0x84, 0x7e, 0x18,
                                      0x64, 0x76, 0x6e, 0x63, 0x64, 0x7a, 0x5f,
                                      0x84, 0x7f, 0x9a};

//Decrypt byte[]
public static byte[] Decrypt(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    Rijndael alg = Rijndael.Create();
    alg.Key = Key;
    CryptoStream cs = new CryptoStream(ms,
    alg.CreateDecryptor(), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.Close();
    byte[] decryptedData = ms.ToArray();
    return decryptedData;
}

//Encrypt byte[]
public static byte[] Encrypt(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    Rijndael alg = Rijndael.Create();
    alg.Key = Key;
    CryptoStream cs = new CryptoStream(ms,
    alg.CreateEncryptor(), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.Close();
    byte[] encryptedData = ms.ToArray();
    return encryptedData;
}

//serialize object to memory stream
public static MemoryStream SerializeToStream(object o)
{
    MemoryStream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, o);
    return stream;
}

//deserialize object from memory stream
public static T DerializeFromStream<T>(MemoryStream memoryStream) where T : new()
{
    if (memoryStream == null) { return new T(); }
    T o;
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (memoryStream)
    {
        memoryStream.Seek(0, SeekOrigin.Begin);
        o = (T)binaryFormatter.Deserialize(memoryStream);
    }
    return o;
}

这是使用上述实用功能的测试

//serialize to stream then to byte array
var obj = new SomeObject();
var bytes = SerializeToStream(obj).ToArray();
bytes = Encrypt(bytes);

//deserialize to decrypted byte array then to stream then to object
var memoryStream = new MemoryStream();
var Decryptedbytearray = Decrypt(bytes);
//fille the stream
memoryStream.Write(Decryptedbytearray, 0, Decryptedbytearray.Length);
//deserialize the object from the stream
//it fails here giving an exception saying the binary data is not valid
var obj2 = DerializeFromStream<SomeObject>(memoryStream);

反序列化对象时出现问题,请参阅注释的最后一行,我做错了什么?

2 个答案:

答案 0 :(得分:4)

如果您调试代码,您将看到它没有正确解密。原因是您不仅要使用相同的key,还要使用相同的IV

来自MSDN

  

每当您创建其中一个SymmetricAlgorithm类的新实例或手动调用GenerateIV方法时,IV属性会自动设置为新的随机值。 IV属性的大小必须与BlockSize属性除以8相同。

请查看this question,了解有关如何使用密码创建密钥和IV的详细信息。

答案 1 :(得分:0)

有一种简单的方法可以生成字节数组的加密版本。

看看这个作为安全Baseclass一部分的sniped代码,它被设计为对数组的访问权限有限,这个代码在实例级别进行加密。  在查看它时,您会明白实际上当您更改“盐”时,您可以非常轻松地更改范围。我抓住了错误,并没有提出它们,这可以被认为是错误的编码但是提供错误使黑客更容易理解如何通过你想要保护的东西......,这里是代码:

internal class Protected
{
    private  Byte[] salt = Guid.NewGuid().ToByteArray();

    protected byte[] Protect(byte[] data)
    {
        try
        {
            return ProtectedData.Protect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }

    protected byte[] Unprotect(byte[] data)
    {
        try
        {
            return ProtectedData.Unprotect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }
}

类ProtectedData来自命名空间System.Security.Cryptography,可以在Core 2.0中的NuGet包System.Security.Cryptography.ProtectedData中找到