如何从Windows Vault凭据管理器存储和检索凭据?

时间:2012-02-10 00:50:01

标签: security winapi authentication credentials dpapi

我想在Windows PC上安全地存储明文密码。我目前正在使用DPAPI CryptProtectData对其进行加密,然后将加密的blob存储在用户本地AppData中的文件中。

在Windows 7中,有Windows Vault,凭据管理器(控制面板\用户帐户和家庭安全\凭据管理器),用于存储各种登录类型的登录数据,包括“通用凭据”。从表面上看,这似乎是程序存储凭据的正确位置。但是,我无法找到任何API。我在MSDN中阅读了Authentication function引用,但坦率地说它迷失了。

Windows Vault是否存在用于存储和检索程序凭据的API,如果有,我在哪里可以找到文档?

3 个答案:

答案 0 :(得分:33)

非常感谢@Luke的提示:用于在Windows Vault中存储凭据和从Windows Vault读取凭据的Windows API函数是CredWrite()CredRead()。这是一个可以编译和运行的代码示例,我曾经确认这些函数确实做了预期的事情:

#include <windows.h>
#include <wincred.h>
#include <tchar.h>
#pragma hdrstop

void main ()
{
    { //--- SAVE
        char* password = "brillant";
        DWORD cbCreds = 1 + strlen(password);

        CREDENTIALW cred = {0};
        cred.Type = CRED_TYPE_GENERIC;
        cred.TargetName = L"FOO/account";
        cred.CredentialBlobSize = cbCreds;
        cred.CredentialBlob = (LPBYTE) password;
        cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
        cred.UserName = L"paula";

        BOOL ok = ::CredWriteW (&cred, 0);
        wprintf (L"CredWrite() - errno %d\n", ok ? 0 : ::GetLastError());
        if (!ok) exit(1);
    }
    { //--- RETRIEVE
        PCREDENTIALW pcred;
        BOOL ok = ::CredReadW (L"FOO/account", CRED_TYPE_GENERIC, 0, &pcred);
        wprintf (L"CredRead() - errno %d\n", ok ? 0 : ::GetLastError());
        if (!ok) exit(1);
        wprintf (L"Read username = '%s', password='%S' (%d bytes)\n", 
                 pcred->UserName, (char*)pcred->CredentialBlob, pcred->CredentialBlobSize);
        // must free memory allocated by CredRead()!
        ::CredFree (pcred);
    }
}

通用凭据存储在Windows Vault中,如屏幕截图所示:

A generic credential stored in Windows Vault

答案 1 :(得分:15)

对于很晚才加入帖子的人来说,有一个新的库可以在Windows 8中与这个商店进行交互,名为:Windows.Security.Credentials.PasswordVault

实际上,只需两行powershell即可使用该类查看当前用户帐户下存储的所有用户名和密码:

[void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]
(new-object Windows.Security.Credentials.PasswordVault).RetrieveAll() | % { $_.RetrievePassword(); $_ }

答案 2 :(得分:7)

如果有人有兴趣从PowerShell或C#读取和写入它,这里有一个指向脚本的链接:

PowerShell Credentials Manager: CredMan.ps1

PowerShell脚本通过使用Pinvoke的内联C#访问API。