使用 XML 序列化时保护敏感值(密码)
本文关键字:密码 XML 序列化 保护 使用 | 更新日期: 2023-09-27 18:31:23
我们有一个保存用户登录配置文件的类,这是一个简单的类,我们只是序列化到磁盘。 我们当然可以加密、压缩等序列化过程,但是,出于其他原因,我想保持简单。
序列化的一项是密码 (字符串) 属性。 我不介意它被序列化,但我希望序列化的值是 3DES 加密的,这样如果有人在某个阅读器中打开文件,它不会损害密码。 我知道我可以简单地将密码值设置为加密值并获取加密值,但我想稍微自动化一下,以便在调用 GET'er 时处理解密,SET'er 处理加密,因此它是无缝的。
你建议最好的方法是什么? 我在想的是我需要将"密码"属性标记为序列化程序忽略,它只是指向另一个属性的路径,该属性保存加密值并因此返回解密。 这是处理此问题的最佳/唯一方法吗? 只是想看看是否有更简单的方法,然后再通过我可以看到的唯一方法对其进行编码,以将加密/解密保持在序列化类逻辑中。
谢谢。
您可以将密码属性标记为序列化忽略,并使用要序列化的包装器属性:
public class LogonInfo
{
[XmlIgnore]
public string Password { get; set; }
public string EncPassword {
{
get
{
return Encrypt(Password);
}
set
{
Password = Decrypt(value);
}
}
// TODO: add Encrypt and Decrypt methods
}
您可以使用 ExtendedXmlSerializer。如果某个类具有需要加密的属性:
public class Person
{
public string Name { get; set; }
public string Password { get; set; }
}
您必须实现接口 IPropertyEncryption。例如,它将显示 Base64 编码,但在现实世界中最好使用更安全的东西,例如。RSA.:
public class Base64PropertyEncryption : IPropertyEncryption
{
public string Encrypt(string value)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
}
public string Decrypt(string value)
{
return Encoding.UTF8.GetString(Convert.FromBase64String(value));
}
}
在 Person 类配置中,您需要指定要加密的属性:
public class PersonConfig : ExtendedXmlSerializerConfig<Person>
{
public PersonConfig()
{
Encrypt(p => p.Password);
}
}
然后,您必须注册 PersonConfig 类和 IPropertyEncryption 的实现。在文档中描述了使用 Autofac 的配置。有简单的配置:
var toolsFactory = new SimpleSerializationToolsFactory();
// Register your config class
toolsFactory.Configurations.Add(new PersonConfig());
// If you want to use property encryption you must register your implementation of IPropertyEncryption, e.g.:
toolsFactory.EncryptionAlgorithm = new Base64PropertyEncryption();
ExtendedXmlSerializer serializer = new ExtendedXmlSerializer(toolsFactory);
然后你可以序列化对象:
var obj = new Person {Name = "John", Password = "Ab238ds2"};
var xml = serializer.Serialize(obj);
您的 xml 将如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Person type="ExtendedXmlSerialization.Samples.Encrypt.Person">
<Name>John</Name>
<Password>QWIyMzhkczI=</Password>
</Person>
ExtendedXmlSerializer 还有许多其他有用的功能:
- 从标准 XMLSerializer 反序列化 xml
- 具有属性接口的序列化类
- 序列化循环引用和引用 ID
- 旧版本的 xml 的反序列化
- 属性加密
- 自定义序列化程序
ExtendedXmlSerializer 支持 .net 4.5 和 .net Core。您可以将其与WebApi和AspCore集成。
我会使用您喜欢的任何方法存储密码的哈希值,例如 MD5。在内存或磁盘上,实际密码都不会存储。然后,要进行身份验证,请获取输入的明文密码,再次对其进行哈希处理,并根据存储的哈希进行检查。这样,身份验证仍然有效,但除了初始输入之外,密码明文不可用。在初始输入期间,密码很容易受到攻击,因为它必须在接收数据和散列数据之间位于内存中以进行比较。由于这个时间很短,攻击不太可能,但有可能。
在程序的这个阶段,SecureString将是散列之前存储密码的不错选择。这在哈希之前提供密码的自动加密,并允许您指定何时从内存中删除对象。
如果第三方获得哈希,这对他们来说是无用的,因为它是不可逆的。此外,如果他们尝试使用哈希登录,您的程序将再次对其进行哈希处理,但检查失败。为了更加偏执,您也可以始终加密整个文件!
我假设这是在本地发生的,或者网络连接是加密的(例如,https)。根据上面的评论,切勿通过网络发送明文密码。