C# 如何在应用程序中加密用户设置(如密码)?

C# 如何在应用程序中加密用户设置(如密码)?,c#,.net,winforms,C#,.net,Winforms,我想为用户提供加密保存个人数据的能力。这可能是微不足道的,或者可能已经被问过了,但我找不到一个简单易用的密码加密/解密方法的示例 我真的不需要任何超级神奇的牢不可破的密码。我只需要密码就像很难破解一样 我看到了一些MSDN等问题,但还没有找到可以使用的东西。以下内容非常简单,假设您真的只想加密/解密字符串并将其存储到磁盘。注意:这不使用密码,而是使用登录用户System.security.Cryptography.DataProtectionScope.CurrentUser的安全上下文来保护数

我想为用户提供加密保存个人数据的能力。这可能是微不足道的,或者可能已经被问过了,但我找不到一个简单易用的密码加密/解密方法的示例

我真的不需要任何超级神奇的牢不可破的密码。我只需要密码就像很难破解一样


我看到了一些MSDN等问题,但还没有找到可以使用的东西。

以下内容非常简单,假设您真的只想加密/解密字符串并将其存储到磁盘。注意:这不使用密码,而是使用登录用户System.security.Cryptography.DataProtectionScope.CurrentUser的安全上下文来保护数据

public class SecureIt
{
    static byte[] entropy = System.Text.Encoding.Unicode.GetBytes("Salt Is Not A Password");

    public static string EncryptString(System.Security.SecureString input)
    {
        byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
            System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
            entropy,
            System.Security.Cryptography.DataProtectionScope.CurrentUser);
        return Convert.ToBase64String(encryptedData);
    }

    public static SecureString DecryptString(string encryptedData)
    {
        try
        {
            byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
                Convert.FromBase64String(encryptedData),
                entropy,
                System.Security.Cryptography.DataProtectionScope.CurrentUser);
            return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
        }
        catch
        {
            return new SecureString();
        }
    }

    public static SecureString ToSecureString(string input)
    {
        SecureString secure = new SecureString();
        foreach (char c in input)
        {
            secure.AppendChar(c);
        }
        secure.MakeReadOnly();
        return secure;
    }

    public static string ToInsecureString(SecureString input)
    {
        string returnValue = string.Empty;
        IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
        try
        {
            returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
        }
        finally
        {
            System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
        }
        return returnValue;
    }

}
然后,要加密字符串:

  var clearText = "Some string to encrypt";
  var cypherText = SecureIt.EncryptString( SecureIt.ToSecureString( clearText));
并随后解密:

var clearText = SecureIt.ToInsecureString( SecureIt.DecryptString(cypherText));
,我认为它很漂亮,但我认为作为扩展方法,它们会更漂亮。这将允许以下语法:

string cypherText;
string clearText;

using (var secureString = "Some string to encrypt".ToSecureString())
{
    cypherText = secureString.EncryptString();
}

using (var secureString = cypherText.DecryptString())
{
    clearText = secureString.ToInsecureString();
}
以下是更新的代码:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;

public static class SecureIt
{
    private static readonly byte[] entropy = Encoding.Unicode.GetBytes("Salt Is Not A Password");

    public static string EncryptString(this SecureString input)
    {
        if (input == null)
        {
            return null;
        }

        var encryptedData = ProtectedData.Protect(
            Encoding.Unicode.GetBytes(input.ToInsecureString()),
            entropy,
            DataProtectionScope.CurrentUser);

        return Convert.ToBase64String(encryptedData);
    }

    public static SecureString DecryptString(this string encryptedData)
    {
        if (encryptedData == null)
        {
            return null;
        }

        try
        {
            var decryptedData = ProtectedData.Unprotect(
                Convert.FromBase64String(encryptedData),
                entropy,
                DataProtectionScope.CurrentUser);

            return Encoding.Unicode.GetString(decryptedData).ToSecureString();
        }
        catch
        {
            return new SecureString();
        }
    }

    public static SecureString ToSecureString(this IEnumerable<char> input)
    {
        if (input == null)
        {
            return null;
        }

        var secure = new SecureString();

        foreach (var c in input)
        {
            secure.AppendChar(c);
        }

        secure.MakeReadOnly();
        return secure;
    }

    public static string ToInsecureString(this SecureString input)
    {
        if (input == null)
        {
            return null;
        }

        var ptr = Marshal.SecureStringToBSTR(input);

        try
        {
            return Marshal.PtrToStringBSTR(ptr);
        }
        finally
        {
            Marshal.ZeroFreeBSTR(ptr);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
使用系统安全;
使用System.Security.Cryptography;
使用系统文本;
公共静态类SecureIt
{
私有静态只读字节[]熵=Encoding.Unicode.GetBytes(“Salt不是密码”);
公共静态字符串EncryptString(此SecureString输入)
{
如果(输入==null)
{
返回null;
}
var encryptedData=ProtectedData.Protect(
Encoding.Unicode.GetBytes(input.ToInsecureString()),
熵,
DataProtectionScope.CurrentUser);
返回Convert.tobase64字符串(encryptedData);
}
公共静态SecureString DecryptedString(此字符串加密数据)
{
如果(encryptedData==null)
{
返回null;
}
尝试
{
var decryptedData=ProtectedData.Unprotect(
转换.FromBase64String(encryptedData),
熵,
DataProtectionScope.CurrentUser);
返回Encoding.Unicode.GetString(decryptedData.ToSecuriting();
}
抓住
{
返回新的SecureString();
}
}
公共静态SecureString到安全性(此IEnumerable输入)
{
如果(输入==null)
{
返回null;
}
var secure=new SecureString();
foreach(输入中的var c)
{
安全的。附加字符(c);
}
secure.MakeReadOnly();
安全返回;
}
公共静态字符串到InsecureString(此SecureString输入)
{
如果(输入==null)
{
返回null;
}
var ptr=Marshal.SecureStringToBSTR(输入);
尝试
{
返回Marshal.PtrToStringBSTR(ptr);
}
最后
{
ZeroFreeBSTR元帅(ptr);
}
}
}
出于我的目的,我修改了解决方案,不使用
SecureString
,因为保护内存对我来说并不重要。我只需要序列化加密字符串。要进行此工作项目,需要参考
System.Security
(不仅仅使用语句)

使用它:

string cypherText = "My string".EncryptString();
string clearText = cypherText.DecryptString();

相关问题:。还有很多,更多:。请注意,无论你做什么,你都不会解密密码。而是确保两个散列匹配。@CodyGray有办法在sql连接字符串中发送散列密码吗?我对sql一无所知,但我相信一定有办法。哈希密码与任何其他文本或数值完全相同。您不希望在连接字符串中使用用户密码。假设您在SQL Server上,这样做会防止连接被池化,从而降低性能。相反,使用一个使用Windows身份验证连接到SQL Server的帐户。这是一个很好的改进。我从一个旧的单元测试项目中复制了代码,在那里我使用实际的用户帐户和密码进行测试。我想安全地存储密码,这样我就可以运行测试,而不必在明文中显示或记录密码。请参阅我在@DavidClarke的回答中留下的注释,并查看此相关的
ToInsecureString
是否违背了使用
SecureString
s的目的?如果您将机密转换为
字符串
,并将其保存在内存中,则最好从简单的
字符串
开始。如果您解密安全字符串,则使用安全字符串没有意义。其全部目的是将整个字符串保留在单个内存块之外。使用此方法并不比只获取字符串并对其进行加密要好:
永远不应该从字符串构造SecureString对象,因为敏感数据已经受到不可变字符串类的内存持久性影响。构造SecureString对象的最佳方法是从一个字符一个字符的非托管源,例如Console.ReadKey方法。
这是一个很好的观点。我并不是说所有的方法都应该在同一个应用程序中使用。在将字符串安全地存储在单元测试项目的设置中之前,我使用了一个单独的控制台应用程序来捕获字符串并对其进行加密。目的是为其使用的环境提供足够的安全性。
string cypherText = "My string".EncryptString();
string clearText = cypherText.DecryptString();