保存安全字符串

时间:2020-03-06 14:51:46  来源:igfitidea点击:

我对正在使用的程序具有的功能要求之一是能够保存用户输入的凭据列表,以便可以共享它们。激发此请求的特定用例是在大型公司网络上使用我们的程序,该公司网络由通过不稳定WAN连接的相当不错的局域网组成。他们的想法是,与其让我们的程序在出现故障时与WAN对抗,不如发送一个包含紧密管理的管理员凭据的"配置"文件,在每个LAN中运行该文件并压缩结果并通过电子邮件发送背部。

是的。

我的本能是嘲笑此请求以保存密码?真的吗?并且公司的网络部门肯定希望我们尝试销售他们拥有的任何WAN产品,但事实证明,我使用凭据的类之一可以采用SecureString,而且,寻找方法总是很不错的我们可以节省一些精力。这让我想知道:

是否可以保存加密的SecureString,以便我可以将敏感数据保存到文件中并在其他地方打开它?

我们有什么想法,堆栈溢出?

解决方案

如果我们要保存SecureString的加密字节,则将无法正常工作,因为SecureString的密钥已与用户和进程绑定在一起。以不同的过程或者不同的用户读取这些字节,就无法解密该字符串。

我们可能需要看一看IsolatedStorageFileStream类。它指定了只能由程序集访问的写入和存储文件数据的方式。

我不认为我们可以在上面使用SecureString。

SecureString不可序列化,因此我们不能仅将其与某些交付的序列化程序(二进制,XML等)一起保存。

我们也不能仅访问例如来自安全字符串对象的"密码"属性,因为没有这种东西。
我们必须使用编组和一点点管道来做到这一点。
如果我们想将用户凭证存储在某个地方,建议我们自行加密,以方便以后的开发。在评估了SecureString方法之后,我们决定自己实现一些东西,但这只是我的2美分。

这将破坏SecureString的观点,后者可以保证驻留在内存中。因此,如果将其保存到文件中,则最好将其另存为普通字符串,因为它不再是"安全的"。

SecureString中没有保存支持,它旨在保护内存中托管字符串的机制,仅用于与非托管API的接口。如果密码存储在System.String实例中,则由于System.String的性质,安全性会降低。垃圾回收和实习的存在将使密码在内存中的保留时间超过必要的时间。同样,由于存在大量的.NET调试工具,即使没有更长的生存期,通过反射或者其他.NET API访问字符串也将变得更加容易。

如果要在磁盘上保存密码,则安全性将受到很大影响。如果某人具有对计算机的物理访问权限,或者具有管理员级别的远程访问权限,那么我们能做的最好的事情就是使它变得更加困难,但绝不可能。使用加密API,将其存储在安全的位置,配置访问权限。

除了所有这些,Merus,我建议我们尝试改进整个系统,因为对于我们正在描述的用例(假设我理解),最好使用存储散列而不是实际密码。

我们可能需要查看比较密码哈希。
我们会得到一个由用户名和其他常量组成的字符串,后跟字符串。然后,将其传递给哈希算法,例如SHA1 *。
例如,

using System.Security.Cryptography;

public byte[] GetPasswordHash(string username, string password, string salt)
{
    // get salted byte[] buffer, containing username, password and some (constant) salt
    byte[] buffer;
    using (MemoryStream stream = new MemoryStream())
    using (StreamWriter writer = new StreamWriter(stream))
    {
        writer.Write(salt);
        writer.Write(username);
        writer.Write(password);
        writer.Flush();

        buffer = stream.ToArray();
    }

    // create a hash
    SHA1 sha1 = SHA1.Create();
    return sha1.ComputeHash(buffer);
}

然后,我们将把" GetPasswordHash(用户名,期望密码,盐)"的结果与" GetPasswordHash(用户名,给定密码,盐)"进行比较。
如果使用用户名和密码实现自己的用户列表,则可以考虑仅保存哈希(" GetPasswordHash(用户名,givenPassword,salt)"),然后与保存的哈希进行比较。