securitywinapiauthenticationcredentialsdpapi

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


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?


Solution

  • 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 <wchar.h>
    #pragma hdrstop
    
    #pragma comment(lib, "advapi32.lib")  // Or pass it to the cl command line.
    
    int 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);
            // Memory allocated by CredRead() must be freed!
            ::CredFree (pcred);
        }
    }
    

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

    A generic credential stored in Windows Vault

    Addendum: Vault vs Crypto DP API

    The answer appears to be quite popular, and is upvoted regularly for nearly 6 years since I wrote it. There were questions raised in the comments about the difference between storing credentials in the vault and encrypting a credential blob with the ::CryptProtectData() API and storing it whenever one pleases. Here's my understanding, possibly non-exhaustive, of the key differences.

    In summary, Vault is a higher-level, narrowly-targeted API for keeping user-visible, user-managed credentials and other identity-related secrets, managed through the system UI. CryptProtectData() is a general use encryption API, with more flexibility and more code needed to be written and audited to manage persisted ciphertext safely.

    The question which of the two is "more secure" is ill-posed. There is no definition of "more or less secure" that could apply to any use of encryption across the board.