0

对于 C# 控制台应用程序,我需要在应用程序设置中保留密码,但是当我创建类型设置时System.Security.SecureString,设置本身会从纯文本配置文件中删除。由于我再也看不到原始值,因此无法验证数据在保存时是否仍处于加密状态。

SecureString最好的方法还是我应该ProtectedData用来简单地加密字符串?

--EDIT-- 这是我用来验证 aSecureString可以持久化的测试代码。

        [global::System.Configuration.ApplicationScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public global::System.Security.SecureString Password
        {
            get
            {
                return ((global::System.Security.SecureString)(this["Password"]));
            }
            set { this["Password"] = value; }
        }

        static void Main(string[] args)
        {
            PersistPassword("A-Test-Password");
            Console.WriteLine(ReadPassword());
            Console.ReadLine();
        }

        static void PersistPassword(string Password)
        {
            SecureString ss = new SecureString();
            Password.ToCharArray().ToList().ForEach(ss.AppendChar);
            Settings.Default.Password = ss;
        }

        static string ReadPassword()
        {
            SecureString ss = Settings.Default.Password;
            IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(ss);
            return Marshal.PtrToStringUni(ptr);
        }
4

2 回答 2

1

正如MSDN中所述,

当初始化实例或修改值时,使用底层平台支持的机制自动保护 SecureString 实例的值。

如果您想提供一种机制,使其在密码存储在安全字符串中时保持只读,那么您可以MarkAsReadonly()在其上调用该方法。

出于持久性目的,您还可以散列SecureString并为其创建盐。您可以检索盐供以后使用,例如比较目的。查看这个使用 salt over 的代码片段Securestring

于 2015-09-04T19:20:41.947 回答
1

您不能持久保存使用SecureString加密的数据。密钥保存在内存中,并且仅在您的程序存在时才持续。SecureString 是原生CryptProtectMemory函数的包装器。

如果您需要加密数据是可持久的(比您的程序存在的时间长),您需要数据保护 API (DPAPI),它是CryptProtectData函数 - 通过ProtectedData类向 C# 用户公开。

SecureString具有短暂性的优点;对...有用:

  • 密码
  • 信用卡号码
  • 社会保险号码

当它们被您的程序使用时 - 然后被删除。

DPAPI 更适合长期存储。但请注意保护级别,并选择适合您需要的保护级别:

  • 只能由我解密
  • 只能在这台电脑上解密
  • 只能由域中的任何人解密

如果您需要可以在传输到不同站点或不同域的过程中幸存的加密:CryptProtectData 不适合您。

四个级别

  • CryptProtectMemory(.NET 中的 SecureString):仅在进程内存中有用
  • CryptProtectData(.NET 中的ProtectedData):加密数据块,您可以将其存储在任何您喜欢的位置(内存、注册表、硬盘)——但您必须自己存储。
  • CredWrite:使用CryptProtectData加密密码,并将其存储在 Windows 密码库中(开始 → 凭据管理器)
  • CredUIPromptForCredentials / CredUIConfirmCredentials :提示用户输入密码,对其进行加密,并使用CredWrite将其保存在密码库(开始 → 凭据管理器)中
于 2019-01-18T22:27:07.837 回答