如何在C#中对对象进行序列化并防止篡改?

3

我有一个C#类,如下所示:

public class TestObj
{
    private int intval;
    private string stringval;
    private int[] intarray;
    private string[] stringarray;

    //... public properties not shown here
}

我希望将这个类的实例序列化为一个字符串。
此外:
我将把这个字符串作为QueryString参数附加到URL中。因此,我希望采取一些措施,确保字符串不能轻易被篡改。
此外,我希望序列化方法高效,以使字符串大小最小化。
有什么具体的.NET Framework类/方法建议使用吗?
2个回答

4

1)序列化:

 public String SerializeObject(TestObj object)
 {
        String Serialized = String.Empty;
        MemoryStream memoryStream = new MemoryStream ( );
        XmlSerializer xs = new XmlSerializer(typeof(TestObj));
        XmlTextWriter xmlTextWriter = new XmlTextWriter ( memoryStream, Encoding.UTF8 );
        xs.Serialize (xmlTextWriter, object);
        memoryStream = (MemoryStream) xmlTextWriter.BaseStream;
        Serialized = UTF8Encoding.GetString(memoryStream.ToArray());
        return Serialized;
 }

2) 为了防止篡改:

  • 想一个秘密字符串,例如“MySecretWord”。
  • 将序列化的对象实例作为字符串,然后将秘密字符串附加到其末尾。
  • 对字符串进行哈希处理(例如SHA,或者使用Remus建议的HMAC)
  • 将哈希值添加到查询字符串中

在接收端(也知道“MySecretWord”秘密字符串),您要去除哈希值,取出原始序列化实例,附加已知的秘密字符串并再次进行哈希。 然后比较两个哈希值是否相等。 如果相等,则字符串没有被修改。

您可能需要对字符串进行Url / Base64编码,以便它可以作为查询字符串工作。 这也很重要,因为您需要确保查询字符串恰好按发送的方式到达。


这个问题在于它没有解决与目标共享或更新密钥的问题。假设如果他想要防止篡改,那么另一方需要知道如何检查无效值。此外,如果他使用可预测的密钥,那么有人可以篡改对象并重新计算哈希值。 - Omniwombat
不要重复造轮子。CLR提供了开箱即用的HMAC签名,由专业的密码学家进行了审查。 - Remus Rusanu
1
@Omniwombat: 这显然不是高安全场景,因为他正在处理信息的查询字符串传输。秘密的存在就足以让任何“攻击者”无从下手。此外,秘密可以选择无限复杂,这使得哈希解决方案可扩展到安全需求,但在这种情况下,我宁愿沿着线路加密整个字符串。无论哪种方式,对于任何防篡改的内容,他都需要访问目标位置。 - Alex
@Alex 注意使用类似“肯定不是高安全场景”和“将使任何‘攻击者’失去平衡”的术语。我们不知道他的要求,也永远不会有技术能够保证挫败所有攻击。(另外,我认为你的意思是“任意复杂”。) - Omniwombat
3
@Omniwombat:我可以整天留下评论批评别人的解决方案。我已经为他提供了一个快速解决他需求的解决方案,而不是帮助他编写完全支持OTP的RSA异步加密,符合银行标准的解决方案。关键点:我没有看到你提供答案。你能给我们展示一下你的代码魔法吗?它应该是可重用的、高度安全的、稳定的、处理开销低的,没有内存占用,并且也许还能在我们需要的时候泡咖啡。 - Alex

4

签名流并将签名添加到查询中。使用HMAC签名算法,例如HMACSHA1。您需要在客户端和服务器之间拥有一个秘密来签署和验证签名。


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