Подтвердить что ты не робот

Как хранить и извлекать учетные данные из диспетчера учетных данных Windows Vault?

Я хочу безопасно хранить пароль открытого текста на ПК с ОС Windows. В настоящее время я использую DPAPI CryptProtectData, чтобы зашифровать его, а затем сохранить зашифрованную блоб в файле в локальной локальной AppData пользователя.

В Windows 7 существует Windows Vault, менеджер учетных данных (Панель управления\Учетные записи пользователей и Семейная безопасность\Диспетчер учетных данных), в котором хранятся данные входа для различных типов входа, включая "общие учетные данные". На первый взгляд это выглядит как подходящее место для хранения учетных данных. Однако я не смог найти API для этого. Я прочитал функцию проверки подлинности в MSDN, но откровенно заблудился в ней.

Есть ли API для Windows Vault для хранения и получения учетных данных из программы и, если да, где я могу найти документацию?

4b9b3361

Ответ 1

Большое спасибо @Luke за подсказку: функции Windows API для хранения учетных данных и их чтения из Windows Vault: 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

Ответ 2

Для тех, кто поздно присоединяется к потоку, в 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(); $_ }

Обновление: Похоже, что Microsoft (к счастью) ограничил этот API больше в Windows 10, и он больше не будет сбрасывать все ваши пароли так тривиально. Это только указание на изменение, которое я видел:

Содержимое шкафчика зависит от приложения или службы. Приложения и службы не имеют доступа к учетным данным, связанным с другими приложениями или службами.

Ответ 3

Если кто-то заинтересован в чтении и записи в PowerShell или С#, здесь ссылается на script:

Менеджер учетных данных PowerShell: CredMan.ps1

PowerShell script обращается к API через встроенный С#, который использует Pinvoke.