How do I store and retrieve credentials from the Windows Vault credential manager?
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:
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.
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.