web-dev-qa-db-ja.com

Windows Vault資格情報マネージャーから資格情報を保存および取得するにはどうすればよいですか?

Windows PCにプレーンテキストパスワードを安全に保存したい。現在、DPAPI CryptProtectData を使用して暗号化し、暗号化されたblobをユーザーのローカルAppDataのファイルに保存しています。

Windows 7には、「一般的な資格情報」を含むさまざまなログオンタイプのログオンデータを格納する資格情報マネージャー(コントロールパネル\ユーザーアカウントおよび家族の安全\資格情報マネージャー)であるWindows Vaultがあります。表面上は、資格情報を保存するプログラムの適切な場所のように見えます。ただし、そのためのAPIを見つけることができませんでした。 MSDNで Authentication function referenceを読みましたが、率直に言って失われました。

プログラムから資格情報を保存および取得するためのWindows VaultへのAPIはありますか?はいの場合、ドキュメントはどこにありますか?

32
kkm

ヒントについて@Lukeに感謝します。WindowsVaultに資格情報を保存して読み取るための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

33
kkm

スレッドに遅れて参加する人のために、Windows 8でこのストアと対話する新しいライブラリがあります:Windows.Security.Credentials.PasswordVault

実際、クラスを使用して現在のユーザーアカウントに保存されているすべてのユーザー名とパスワードを表示するには、2行のpowershellだけが必要です。

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

Update: Windows 10ではMicrosoftが(ありがたいことに)このAPIをさらに制限し、すべてのパスワードをダンプしなくなったようですとても些細なことです。これは、私が見た変更を示しているだけです。

ロッカーの内容は、アプリまたはサービスに固有です。アプリとサービスは、他のアプリまたはサービスに関連付けられた資格情報にアクセスできません。

16
Tim

PowerShellまたはC#からの読み取りと書き込みに興味がある人は、それを行うスクリプトへのリンクを次に示します。

PowerShell Credentials Manager:CredMan.ps1

PowerShellスクリプトは、Pinvokeを利用するインラインC#を介してAPIにアクセスします。

7
Tim Lewis