【问题标题】:Best practice for saving sensitive data in Windows 8在 Windows 8 中保存敏感数据的最佳实践
【发布时间】:2014-03-24 07:00:04
【问题描述】:

在 Windows 8 中将敏感数据保存到本地文件的最佳方式是什么?我正在开发一个需要存储 oAuth 令牌/密码的 C# 应用程序。我听说在 .NET 中加密/解密数据很常见,但我对这些机制没有任何经验。鉴于 Windows 8 应用程序有自己的类似于 Windows Phone 的个人/受保护存储区域,是否仍建议/需要加密?

另外,每次请求数据时加密/解密不会导致性能问题吗? (写一个自定义/精简算法会更好吗?)

【问题讨论】:

  • 谁是您的威胁模型中的攻击者?系统管理员,还是无特权的流氓软件?
  • 我强烈建议不要开发自己的安全系统要在 Windows 中存储密码,有 凭据管理器(Win7 起)。 WinRtWindows.Security.Credentials 命名空间中有相应的 API,但它的文档仍然很差。

标签: c# windows-8 windows-runtime passwordvault


【解决方案1】:

更新:请注意,虽然现代/都市应用程序被限制互相攻击对方的东西,桌面应用程序将不受限制地访问通过这些 API 存储的所有数据.请参阅 http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx,其中包含演示此内容的代码。


Win8 有一个名为PasswordVault 的新API,专为解决所有这些难题而设计。非常易于使用、安全,并且可以由用户配置为在他们的机器之间漫游,因此他们只需输入一次凭据。我已成功将其用于 OAuth 令牌

检索凭据(注意 WinRT 引发的愚蠢异常......他们真的应该只返回 null):

const string VAULT_RESOURCE = "[My App] Credentials";
string UserName { get; set; };
string Password { get; set; };
var vault = new PasswordVault();

try
{
   var creds = vault.FindAllByResource(VAULT_RESOURCE).FirstOrDefault();
   if (creds != null)
   {
      UserName = creds.UserName;
      Password = vault.Retrieve(VAULT_RESOURCE, UserName).Password;
   }
}
catch(COMException) 
{
   // this exception likely means that no credentials have been stored
}

存储凭据:

vault.Add(new PasswordCredential(VAULT_RESOURCE, UserName, Password));

删除凭据(当用户单击应用中的注销按钮时):

vault.Remove(_vault.Retrieve(VAULT_RESOURCE, UserName));

【讨论】:

  • @RobertLevy 您能否告知我在哪里可以找到有关密码保险库操作可能引发的异常的信息? THX
  • @Louis_PIG - 在 Win8 的预览版中,如果您尝试循环存储库中不存在的内容,则会引发通用 COMException。我不确定在 Win8 的最终 RTM 版本中是否仍然是这种情况
  • @RobertLevy 您能否详细说明您是如何存储 OAuth 令牌的?您是否只是使用“访问令牌”作为用户名和“令牌秘密”作为密码?
  • 不,用户可以禁用所有漫游,但您不能按凭据执行此操作。但是您可以使用户名字段也特定于设备,因此当您从另一台设备查找值时,将找不到它
  • @CodeR:“Credential Locker 对每个 Windows PC 用户都是唯一的并且对凭据的访问仅限于存储它的应用程序blogs.msdn.com/b/windowsappdev/archive/2013/05/30/…
【解决方案2】:

这取决于您的需要,如果您真的需要存储密码,您应该使用 2 路加密算法,如 3DES/RC2/Rijndael 等。

但是,如果您只需要验证密码是否正确,则建议使用单向函数来存储哈希值。

在处理敏感数据时,我真的建议对其进行加密/散列,即使您使用 Windows 8。加密确实意味着额外的开销,但在大多数情况下您不会注意到速度差异。

编写自己的自定义/精简算法会更好吗?作为一名安全人员,我建议不要这样做。人们花费数年时间测试、改进并试图在现有算法中找到漏洞。因此,幸存下来的都很好。

【讨论】:

  • 谢谢,我的应用程序是一个 Twitter 应用程序,它需要为每个请求提供 oAuth 令牌。这些令牌需要在首次获取时保存。现在我在一个 XML 文件中拥有令牌,没有任何加密,并且由于缺乏信息和我对加密的知识缺乏,我“害怕”使用 Windows 8 的加密 API。虽然我知道使用加密是一种很好的做法,即使在 Windows 8 中,我也会尝试通过 Windows.Security.Credentials API 进行操作。感谢大家的帮助
【解决方案3】:

你可以这样加密:

    public static string EncodePassword(string password)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(password);
        byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
        return Convert.ToBase64String(inArray);
    }

并且在检查用户输入时,您还将其放入此方法并检查它是否匹配。

如果您将数据放入要加密/解密的 xml(例如)中,您可以使用 RijndaelManaged。

-Edit1-

一个例子: 如果您有一个弹出的小登录屏幕(ShowDialog),您可以像这样截图:

private void settings_Click(object sender, RoutedEventArgs e)
{
    Login log = new Login();    //login window
    log.ShowDialog();           //show the login window
    string un = log.userName.Text;  //the user input from the username field
    string pw = log.passWord.Password; //the userinput from the password input
    if (EncodePassword(un) == Properties.Settings.Default.adminUsername && EncodePassword(pw) == Properties.Settings.Default.adminPassword) //in my case, i stored it in the app settings, but this could also be somewhere else.
    {
        //login was correct
        //do something
    }
    else
    {
        //login was not correct
    }
}

【讨论】:

  • Nick 的“开发一个需要存储 oAuth 令牌/密码的 C# 应用程序”,因此该应用程序可能需要再次生成这些令牌和密码,在这种情况下存储校验和并丢弃原始不会' t 帮助。
  • 取决于它的用途。如果将其用作密码,则可以将用户输入扔到方法中,并将输出字符串与存储的字符串进行比较。这正是我在我的一个应用程序中的做法。
  • @Dante1986: 当然可以,但我猜(我可能猜错了)Nick 需要存储凭据用于其他应用程序,例如网站 - 所以,如安全客户端,而不是服务器。尼克可能会详细说明他对问题的描述以澄清这一点。
  • 啊,从他的问题来看,我认为他的意思是为他正在制作的同一个应用程序存储通行证。如果他想像数据库或其他东西一样存储它们,上述方法确实行不通。
猜你喜欢
  • 2011-05-17
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 2012-05-10
  • 2017-01-26
相关资源
最近更新 更多