2

我们有一个保存用户登录配置文件的类,它是一个简单的类,我们只需将其序列化到磁盘。我们当然可以对序列化过程进行加密、压缩等,但是,出于其他原因,我想保持简单。

序列化的一项是密码(字符串)属性。我不介意它正在被序列化,但我希望被序列化的值是 3DES 加密的,所以如果有人在某个阅读器中打开文件,它不会泄露密码。我知道我可以简单地将密码值设置为加密值并获取加密值,但我想稍微自动化一下,以便在调用 GET'er 时它处理解密,SET'er 处理加密所以它是无缝的。

您认为解决此问题的最佳方法是什么?我在想的是我需要标记“密码”属性以被序列化程序忽略,它只是指向另一个保存加密值的属性的路径,因此将其返回解密。这是处理此问题的最佳/唯一方法吗?只是想看看是否有更简单的方法,然后再通过我能看到的唯一方法进行编码,以将加密/解密保持在序列化类逻辑中。

谢谢。

4

3 回答 3

11

您可以将密码属性标记为被序列化忽略,并使用某种包装属性进行序列化:

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
}
于 2012-04-17T21:02:21.630 回答
2

您可以使用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 集成。

于 2016-11-15T12:58:01.883 回答
1

我会使用您喜欢的任何方法(例如 MD5)存储密码的散列值。在任何时候,内存或磁盘上都不会存储实际密码。然后进行身份验证,获取输入的明文密码,再次对其进行哈希处理,并根据存储的哈希值进行检查。这样,身份验证仍然有效,但除了初始输入之外,没有其他可用的密码明文。在初始输入期间,密码很容易受到攻击,因为它必须在接收数据和对其进行散列以进行比较之间的内存中。由于这段时间很短,攻击不太可能,但有可能。

在程序的这个阶段,SecureString将是在散列之前存储密码的不错选择。这在散列之前提供密码的自动加密,并允许您指定何时从内存中删除对象。

如果第 3 方获得散列,则对他们来说是无用的,因为使用正确的 alogorithim 是不可逆的。如果他们尝试使用哈希登录,您的程序也会再次对其进行哈希处理,但检查失败。为了更加偏执,您也可以随时加密整个文件!

我假设这是在本地发生的,或者网络连接是加密的(例如,https)。根据上面的评论,永远不要通过网络发送明文密码。

于 2012-04-17T21:02:46.513 回答