Sign in Join
Wiki copytemporary

Windows Credential Storage: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Windows Credential Storage

OldNewLine
1+*(Windows only)*
2+
3+Windows Credential Store allows applications to store user names and passwords in a more secure way, than configuration files can provide.
4+
5+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.
6+
7+``` pascal
8+unit uwincred;
9+
10+// Original Source https://stackoverflow.com/questions/13145112/secure-way-to-store-password-in-windows
11+// adapted for Free Pascal
12+
13+{$mode ObjFPC}{$H+}
14+
15+interface
16+
17+uses
18+ Classes, SysUtils, windows, JwaWinCred;
19+
20+function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
21+function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
22+function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;
23+
24+implementation
25+
26+function WideCharToWideString(s: PWideChar; UnicodeCharCount: SizeInt): UnicodeString;
27+begin
28+ SetLength(Result{%H-}, UnicodeCharCount);
29+ strmove(PWideChar(Result), s, UnicodeCharCount);
30+end;
31+
32+function CredReadGenericCredentials(const Target: UnicodeString; var Username, Password: UnicodeString): Boolean;
33+var
34+ credential: PCREDENTIALW;
35+ le: DWORD;
36+ s: UnicodeString;
37+begin
38+ Result := False;
39+
40+ credential := nil;
41+ if not CredReadW(PWideChar(Target), CRED_TYPE_GENERIC, 0, {var}credential) then
42+ begin
43+ le := GetLastError;
44+ s := 'Could not get "'+Target+'" generic credentials: '+SysErrorMessage(le)+' '+IntToStr(le);
45+ OutputDebugStringW(PWideChar(s));
46+ Exit;
47+ end;
48+
49+ try
50+ username := Credential^.UserName;
51+ password := WideCharToWideString(PWideChar(Credential^.CredentialBlob), Credential^.CredentialBlobSize div 2); //By convention blobs that contain strings do not have a trailing NULL.
52+ finally
53+ CredFree(Credential);
54+ end;
55+
56+ Result := True;
57+end;
58+
59+function CredWriteGenericCredentials(const Target, Username, Password: UnicodeString): Boolean;
60+var
61+ Credentials: CREDENTIALW;
62+begin
63+ ZeroMemory(@Credentials, SizeOf(Credentials));
64+ Credentials.TargetName := PWideChar(Target); //cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters. Recommended format "Company_Target"
65+ Credentials.Type_ := CRED_TYPE_GENERIC;
66+ Credentials.UserName := PWideChar(Username);
67+ Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
68+ Credentials.CredentialBlob := PByte(Password);
69+ Credentials.CredentialBlobSize := 2*(Length(Password)); //By convention no trailing null. Cannot be longer than CRED_MAX_CREDENTIAL_BLOB_SIZE (512) bytes
70+ Credentials.UserName := PWideChar(Username);
71+ Result := CredWriteW(@Credentials, 0);
72+end;
73+
74+function CredDeleteGenericCredentials(const Target: UnicodeString): Boolean;
75+begin
76+ Result := CredDeleteW(PWideChar(Target), CRED_TYPE_GENERIC, 0);
77+end;
78+
79+end.
80+```
81+
82+You can use these functions as following:
83+
84+``` pascal
85+var
86+ StoredUserName, StoredPassword: UnicodeString;
87+begin
88+ StoredUserName := '';
89+ StoredPassword := '';
90+ CredReadGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);
91+ CredWriteGenericCredentials(Application.ExeName, StoredUserName, StoredPassword);
92+ CredDeleteGenericCredentials(Application.ExeName);
93+end;
94+```
95+
96+---
97+*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](/wiki-contact).*
98+Category: Windows

Back to history