如何尽可能安全地解密本地存储的密钥



我有一个需要在应用程序中使用的键。该密钥必须以持久的方式存储在设备上。我需要在不使用用户密码等外部输入的情况下恢复此密钥。任何需要网络/服务器连接的身份验证(除了使用Active Directory对初始系统登录进行身份验证)对我来说都是不可用的。

现在,为了自己解密任何加密的数据,我需要一个解密的私钥,它必须再次存储在某个地方,我不确定这里的最佳实践。

在Windows 7中使用。net存储和解密上述密钥的最安全方法是什么?

您可以通过p/Invoke通过CredReadCredWrite使用凭据库。它是特定于被记录或模拟的用户的,并且不需要密码来解密。

下面是我的一个部署任务的示例,这个示例说明了如何安全地检索只有在下面运行的用户任务才能访问的模拟密码。可通过control /name Microsoft.CredentialManagercmdkey /?CredWrite进行设置。

private Task Impersonate()
{
    if (As == null)
        return this;
    Log.Debug("[As] {0}", As);
    IntPtr token;
    if (!CredRead(As, 1, 0, out token))
        throw new Win32Exception();
    var cred = (Credential)Marshal.PtrToStructure(token, typeof(Credential));
    CredFree(token);
    var name = cred.UserName.Split('\');
    var user = new { Name = name[1], Domain = name[0], Password = Marshal.PtrToStringAuto(cred.CredentialBlob) };
    Log.Info("[As] {0}\{1}", user.Domain, user.Name);
    if (!LogonUser(user.Name, user.Domain, user.Password, 9, 0, out token))
        throw new Win32Exception();
    Context = WindowsIdentity.Impersonate(token);
    if (!CloseHandle(token))
        throw new Win32Exception();
    return this;
}
[DllImport("advapi32", SetLastError = true)]
private static extern bool CredRead(string target, uint type, uint flags, out IntPtr credential);
[DllImport("advapi32", SetLastError = true)]
private static extern void CredFree(IntPtr buffer);
[DllImport("advapi32", SetLastError = true)]
private static extern bool LogonUser(string username, string domain, string password, int type, int provider, out IntPtr token);
[DllImport("kernel32", SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
private struct Credential
{
    #pragma warning disable 169, 649
    public uint Flags;
    public uint Type;
    public string TargetName;
    public string Comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
    public uint CredentialBlobSize;
    public IntPtr CredentialBlob;
    public uint Persist;
    public uint AttributeCount;
    public IntPtr Attributes;
    public string TargetAlias;
    public string UserName;
    #pragma warning restore 169, 649
}

DPAPI应该可以帮助您透明地加密和解密密钥

最新更新