How do I store and retrieve credentials from the Windows Vault credential manager?

流过昼夜 提交于 2019-11-26 06:25:56

问题


I want to securely store a plaintext password on Windows PC. I am currently using DPAPI CryptProtectData to encrypt it, then store the encrypted blob in a file in user\'s local AppData.

In Windows 7, there is Windows Vault, a credential manager (Control Panel\\User Accounts and Family Safety\\Credential Manager) that stores logon data for a variety of logon types, including \"generic credential\". On the surface this looks like the right place for a program to store credentials. However, I was not able to find any API for it. I read Authentication function reference in MSDN, but frankly got lost in it.

Is there an API to Windows Vault to store and retrieve credentials from a program, and, if yes, where can I find documentation?


回答1:


Many thanks to @Luke for the hint: Windows API functions to store credentials to and read them from Windows Vault are CredWrite() and CredRead(). Here is a code sample that may be compiled and run, that I used to confirm that these functions indeed do the expected thing:

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

A generic credential is stored in Windows Vault, as can be seen on the screenshot:




回答2:


For people joining the thread late, there is a new library to interact with this store in Windows 8 called: Windows.Security.Credentials.PasswordVault

In fact it only takes two lines of powershell to use the class to view all user names and passwords stored under the current users account:

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

Update: It looks like Microsoft (thankfully) restricted this api more in Windows 10 and it will no longer dump all your passwords so trivially. This is only indication of the change that I have seen:

The contents of the locker are specific to the app or service. Apps and services don't have access to credentials associated with other apps or services.




回答3:


If anyone is interested in reading and writing to it from PowerShell or C#, here's a link to a script that does it:

PowerShell Credentials Manager: CredMan.ps1

The PowerShell script accesses the API via inline C# that utilizes Pinvoke.



来源:https://stackoverflow.com/questions/9221245/how-do-i-store-and-retrieve-credentials-from-the-windows-vault-credential-manage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!