Sign in Join
Wiki copytemporary

Windows Credential Storage

Deutsch · English

(Windows only)

Windows Credential Store allows applications to store user names and passwords in a more secure way, than configuration files can provide.

The following unit provides three functions to read, write and delete these data in the credential store. You have to provide a Target identifier on each function call.

pascal
unit uwincred;

// Original Source https://stackoverflow.com/questions/13145112/secure-way-to-store-password-in-windows
// adapted for Free Pascal

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, windows, JwaWinCred;

function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;

implementation

function WideCharToWideString(s: PWideChar; UnicodeCharCount: SizeInt): UnicodeString;
begin
  SetLength(Result{%H-}, UnicodeCharCount);
  strmove(PWideChar(Result), s, UnicodeCharCount);
end;

function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
var
    credential: PCREDENTIALW;
    le: DWORD;
    s: UnicodeString;
begin
    Result := False;

    credential := nil;
    if not CredReadW(PWideChar(Target), CRED_TYPE_GENERIC, 0, {var}credential) then
    begin
        le := GetLastError;
        s := 'Could not get "'+Target+'" generic credentials: '+SysErrorMessage(le)+' '+IntToStr(le);
        OutputDebugStringW(PWideChar(s));
        Exit;
    end;

    try
        username := Credential^.UserName;
        password := WideCharToWideString(PWideChar(Credential^.CredentialBlob), Credential^.CredentialBlobSize div 2); //By convention blobs that contain strings do not have a trailing NULL.
    finally
        CredFree(Credential);
    end;

    Result := True;
end;

function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
var
    Credentials: CREDENTIALW;
begin
    ZeroMemory(@Credentials, SizeOf(Credentials));
    Credentials.TargetName := PWideChar(Target); //cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters. Recommended format "Company_Target"
    Credentials.Type_ := CRED_TYPE_GENERIC;
    Credentials.UserName := PWideChar(Username);
    Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
    Credentials.CredentialBlob := PByte(Password);
    Credentials.CredentialBlobSize := 2*(Length(Password)); //By convention no trailing null. Cannot be longer than CRED_MAX_CREDENTIAL_BLOB_SIZE (512) bytes
    Credentials.UserName := PWideChar(Username);
    Result := CredWriteW(@Credentials, 0);
end;

function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;
begin
    Result := CredDeleteW(PWideChar(Target), CRED_TYPE_GENERIC, 0);
end;

end.

You can use these functions as following:

pascal
var
  StoredUserName, StoredPassword: UnicodeString;
begin
  StoredUserName := '';
  StoredPassword := '';
  CredReadGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);
  CredWriteGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);  
  CredDeleteGenericCredentials(Application.ExeName);
end;

From the Free Pascal wiki, page "Windows Credential Storage", as it stood on 2022-09-17 after a change by Bart, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.