Store passwords in scripts securely through Windows Credential Manager API

Post your working scripts, libraries and tools for AHK v1.1 and older
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Store passwords in scripts securely through Windows Credential Manager API

Post by geek » 06 Jan 2023, 16:51

v2 thread

This has been a long-standing item on my todo list, and since it seems that nobody else has piped up about it in the past ten years here we go:

Windows has a built-in credential manager (check your start menu for "Credential Manager") that stores secrets encrypted by your user profile. They cannot be decrypted without your user account credentials (and will be lost if you force an account password reset with something like a recovery boot device). They will be decrypted automatically by Windows when asked for by a program/script running under your user account, so you won't be prompted for a password to decrypt them beyond the windows logon screen you used to log in in the first place.

You can access this credential store to put sensitive information in that you don't want other users to access, or someone who steals your laptop to access. Do note that if your laptop does not have a proper password set on it, it won't be properly encrypted against them just signing in as you and pulling all the passwords. Be sure to choose a unique name, as any program/script running as you shares this store and can access passwords stored in it by that name.

You can put passwords into the store either using AHK, or by opening the credential manager, going to "Windows Credentials", and clicking "Add a generic credential".

Bonus points for those of you in a corporate domain, these passwords will follow your domain profile around to any other computer you sign in to. (if you don't want that, change PERSIST to 2).

Note: this probably won't work for ANSI AHK, but that's just because the code changes to make it support both are painful to write. Someone could port it if they wanted.

Code: Select all

if !CredWrite("AHK_CredForScript1", "SomeUsername", "SomePassword")
	MsgBox failed to write cred

if (cred := CredRead("AHK_CredForScript1"))
	MsgBox % cred.name "," cred.username "," cred.password
else
	MsgBox Cred not found

if !CredDelete("AHK_CredForScript1")
	MsgBox Failed to delete cred

if (cred := CredRead("AHK_CredForScript1"))
	MsgBox % cred.name "," cred.username "," cred.password
else
	MsgBox Cred not found

CredWrite(name, username, password)
{
	VarSetCapacity(cred, 24 + A_PtrSize * 7, 0)
	cbPassword := StrLen(password)*2
	NumPut(1         , cred,  4+A_PtrSize*0, "UInt") ; Type = CRED_TYPE_GENERIC
	NumPut(&name     , cred,  8+A_PtrSize*0, "Ptr")  ; TargetName = name
	NumPut(cbPassword, cred, 16+A_PtrSize*2, "UInt") ; CredentialBlobSize
	NumPut(&password , cred, 16+A_PtrSize*3, "UInt") ; CredentialBlob
	NumPut(3         , cred, 16+A_PtrSize*4, "UInt") ; Persist = CRED_PERSIST_ENTERPRISE (roam across domain)
	NumPut(&username , cred, 24+A_PtrSize*6, "Ptr")  ; UserName
	return DllCall("Advapi32.dll\CredWriteW"
	, "Ptr", &cred ; [in] PCREDENTIALW Credential
	, "UInt", 0    ; [in] DWORD        Flags
	, "UInt") ; BOOL
}

CredDelete(name)
{
	return DllCall("Advapi32.dll\CredDeleteW"
	, "WStr", name ; [in] LPCWSTR TargetName
	, "UInt", 1    ; [in] DWORD   Type,
	, "UInt", 0    ; [in] DWORD   Flags
	, "UInt") ; BOOL
}

CredRead(name)
{
	DllCall("Advapi32.dll\CredReadW"
	, "Str", name   ; [in]  LPCWSTR      TargetName
	, "UInt", 1     ; [in]  DWORD        Type = CRED_TYPE_GENERIC (https://learn.microsoft.com/en-us/windows/win32/api/wincred/ns-wincred-credentiala)
	, "UInt", 0     ; [in]  DWORD        Flags
	, "Ptr*", pCred ; [out] PCREDENTIALW *Credential
	, "UInt") ; BOOL
	if !pCred
		return
	name := StrGet(NumGet(pCred + 8 + A_PtrSize * 0, "UPtr"), 256, "UTF-16")
	username := StrGet(NumGet(pCred + 24 + A_PtrSize * 6, "UPtr"), 256, "UTF-16")
	len := NumGet(pCred + 16 + A_PtrSize * 2, "UInt")
	password := StrGet(NumGet(pCred + 16 + A_PtrSize * 3, "UPtr"), len/2, "UTF-16")
	DllCall("Advapi32.dll\CredFree", "Ptr", pCred)
	return {"name": name, "username": username, "password": password}
}

User avatar
Xeo786
Posts: 759
Joined: 09 Nov 2015, 02:43
Location: Karachi, Pakistan

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by Xeo786 » 07 Jan 2023, 03:11

Nice ..! I am thinking about ways to use it, I haven't got my self into credentials, or Maybe I do not have permission to access them at work.
"When there is no gravity, there is absolute vacuum and light travel with no time" -Game changer theory

User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by Joe Glines » 07 Jan 2023, 09:44

Very cool GeekDude! Thanks for stepping up! I know a lot of people will love this!
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!

User avatar
elModo7
Posts: 217
Joined: 01 Sep 2017, 02:38
Location: Spain
Contact:

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by elModo7 » 08 Jan 2023, 13:09

This could be useful for some projects like a password vault that doesn't rely on having a blank password inside of the script! I'll find usages for it for sure, thank you @geek

timbck2
Posts: 3
Joined: 07 Jun 2023, 15:21
Contact:

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by timbck2 » 07 Jun 2023, 17:29

I'm kind of a newbie to AHK, but I couldn't get this working in AHK 2.0 - it's complaining about the variable 'pCred' never being assigned a value. Is this code only for AHK 1.1?

geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by geek » 07 Jun 2023, 18:17

timbck2 wrote: I'm kind of a newbie to AHK, but I couldn't get this working in AHK 2.0 - it's complaining about the variable 'pCred' never being assigned a value. Is this code only for AHK 1.1?
The V2 code is linked at the top of the original post.

timbck2
Posts: 3
Joined: 07 Jun 2023, 15:21
Contact:

Re: Store passwords in scripts securely through Windows Credential Manager API

Post by timbck2 » 08 Jun 2023, 13:14

geek wrote:
07 Jun 2023, 18:17
The V2 code is linked at the top of the original post.
Thank you! I didn't even see that tiny little link.

Post Reply

Return to “Scripts and Functions (v1)”