2012-02-10 24 views
30

Quiero almacenar de forma segura una contraseña de texto claro en una PC con Windows. Actualmente estoy usando DPAPI CryptProtectData para encriptarlo, luego almaceno el blob cifrado en un archivo en el AppData local del usuario.¿Cómo guardo y recupero las credenciales del administrador de credenciales de Windows Vault?

En Windows 7, hay Windows Vault, un administrador de credenciales (Panel de control \ Cuentas de usuario y Seguridad familiar \ Administrador de credenciales) que almacena datos de inicio de sesión para una variedad de tipos de inicio de sesión, incluida "credencial genérica". En la superficie, este parece el lugar correcto para que un programa almacene credenciales. Sin embargo, no pude encontrar ninguna API para ello. Leí Authentication function referencia en MSDN, pero francamente me perdí en él.

¿Existe una API para Windows Vault para almacenar y recuperar credenciales de un programa y, en caso afirmativo, dónde puedo encontrar la documentación?

+1

Parece CredWrite(), CredRead(), et al en la sección Funciones de administración de credenciales. – Luke

+1

Actualmente estoy buscando soluciones para almacenar las credenciales del usuario. ¿Podría decirme por qué decidió pasar de almacenar el blob cifrado de CryptProtectData a Windows Vault? Más seguridad? Parece menos portátil para las versiones anteriores de Windows (pero por el momento, no estoy seguro de que me importe). – BSchlinker

+0

Al igual que BSchlinker, no entiendo lo que esto nos está ganando. ¿Cómo es esto más seguro que almacenar en el sistema de archivos? – Sammi

Respuesta

31

Muchas gracias a @Luke por la pista: las funciones de la API de Windows para almacenar credenciales y leerlas de Windows Vault son CredWrite() y CredRead(). Aquí está un ejemplo de código que se pueden compilar y ejecutar, que he usado para confirmar que estas funciones efectivamente hacen lo esperado:

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

Una credencial genérica se almacena en Windows Vault, como se puede ver en la captura de pantalla:

A generic credential stored in Windows Vault

+0

¿Hay alguna manera de usar la credencial de una manera que no se pueda recuperar? (como solo iniciar sesión en una URL). – eckes

7

Si alguien está interesado en la lectura y escritura a la misma desde PowerShell o C#, aquí hay un enlace a un script que lo hace:

PowerShell Credentials Manager: CredMan.ps1

La secuencia de comandos de PowerShell accede a la API a través de C# en línea que utiliza Pinvoke.

14

Para personas que entran en el hilo tarde, no es una nueva biblioteca para interactuar con esta tienda en Windows 8 llamada: Windows.Security.Credentials.PasswordVault

De hecho sólo se necesitan dos líneas de PowerShell para utilizar la clase para ver todos los nombres de usuario y contraseñas almacenadas en la cuenta de usuario actual:

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

@ ClairelyClaire Eso seguiría siendo a través de credman. Cuando veo mi credencial de Windows Live a través de la interfaz gráfica de usuario en win8.1, aparece como virtualapp/didlogical con un tipo de genérico. Entonces, si enumera los creds de tipo cred.Type = CRED_TYPE_GENERIC debería encontrar ese. [enlace] (http://answers.microsoft.com/es-us/windows/forum/windows_7-security/unknown-credential-virtualappdidlogical/40467173-a75a-44b2-8617-5aa7a0479925) –

+0

Miré a través de los comandos para el script de PowerShell que publicó Tim Lewis - no estoy seguro de cómo usar el información anterior con eso. Puedo ver la credencial almacenada asociada con la cuenta MS conectada a la cuenta de usuario de Windows 8; simplemente no hay contraseña. – ClairelyClaire

Cuestiones relacionadas