持久化到磁盘时是否必须加密SecureString?

时间:2015-09-04 17:27:15

标签: c# securestring

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

SecureString是最佳方法,还是应该使用ProtectedData来简单加密字符串?

- EDIT-- 以下是我用来验证SecureString可以保留的测试代码。

        [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);
        }

2 个答案:

答案 0 :(得分:1)

作为MSDN中的州,

  

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

如果您希望提供一种机制,只要在securestring中存储密码,就可以将其保密,然后就可以在其上调用方法MarkAsReadonly()

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

答案 1 :(得分:1)

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

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

SecureString 具有短暂的优势;对以下有用:

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

在您的程序正在使用它们时-然后将其删除。

DPAPI更适合长期存储。但是要当心保护级别,然后选择适合您需要的保护级别:

  • 只能由我解密
  • 只能在此PC上解密
  • 只能由域中的任何人解密

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

四个级别

  • CryptProtectMemory (。NET中的SecureeString):仅在进程的内存中有用
  • CryptProtectData (。NET中的ProtectedData):加密一滴数据,您可以将其存储在任意位置(内存,注册表,硬盘)-但必须自己存储。 / li>
  • CredWrite:使用 CryptProtectData 加密密码,并将其存储在Windows密码保管库中(开始→凭据管理器)
  • CredUIPromptForCredentials / CredUIConfirmCredentials :提示用户输入密码,对其进行加密,然后使用 CredWrite < / strong>