guides:passwords_in_scripts

Passwords in Scripts

Let me start by saying…

AutoHotkey is not a replacement for a password manager!!!

At least not without investing time and effort into making a proper password manager out of AHK (and that is completely outside the scope of this post, plus there are already many comprehensive solutions available).

The next thing is to acknowledge pretty obvious points that everyone must be aware of:

  • Everything can be broken.
  • Nothing is ever 100% secure.

But, depending on what you do to protect your information, is how unattractive it becomes for someone looking for whatever can be fished. It is not the same to have a file on the desktop named bank password.txt with your credentials on the clear in there; than have an inconspicuous filename with multi-layered encryption and brute force/dictionary attacks slowed down by key derivation.

Security and cryptography both are really vast and complex topics, if you're interested in them, there are countless communities better suited for that. Here I'm just gonging to demonstrate how to safely have available in AHK a single1) password2) to be used for automation purposes.

Last note before we dig in; if you start an argument with: "If an attacker gains access…", then we are not ever going to achieve anything, you are already exposed at that point; so it is trivial for said attacker to do pretty much anything. The fault is not AHK, the fault was many layers of security before. With or without AHK, the attacker can easily have what it pleases (browsers are a gold mine and keyloggers are meh to write and disguise).


1) It can be adapted to pretty much anything that needs to be secured, not just a single password.
2) Checkout Geek (GeekDude)'s comment as there you have an OS built-in option.

After the longest intro ever…

If you are already using a password manager and following the basic principle of having a strong/complex and lengthy master password, then you are presented with the incredibly cumbersome task of typing it over and over again.

And AHK is about automation and typing for you, right?

I'll present here a secure flow similar to what has been my daily driver for a really long time. At least as secure as cryptography goes, you still have to account for human error and how vulnerable is your system/network (at the end, I'll go about a few points on how to tighten the security a little).

This is what NEVER should be done:

^!p::               ; ← NEVER
    Send qwerty123  ; ←  DO
return              ; ← THIS!

On top of having what is one of the top worst passwords, having it as clear text in a script is against the most basic common sense.

AutoHotkey scripts are not protected in any way1); scripts are NOT compiled, AHK is an interpreted language, and they are converted to an executable. The process is just adding the plain text script contents as a resource of an executable, then the contents are executed same as when reading a file.

Here you have a better approach with the same result (is an oversimplification for demonstrative purposes):

^!p::Send % MasterPassword(A_MyDocuments "\master.dat")
 
MasterPassword(Path) {
    static decrypted := ""
    if (decrypted)
        return decrypted
    FileRead encrypted, % Path
    loop 3 {
        InputBox key, Encryption Key:,, Hide, 200, 100
        decrypted := Decrypt(encrypted, key)
        return decrypted
    }
    MsgBox 0x40010, Error, Password couldn't be decrypted.
}

What the above does?

First, the password is not stored in the script but loaded from an encrypted file called master.dat; upon the first usage, you are prompted to provide the encryption key and have the 3 standard opportunities to decrypt your password. When successful, the password is kept unencrypted in memory) and ready for later usage.

The result is as secure as the encryption method you used to encrypt your password. And yes, you can safely encrypt your master password with (drumroll)… your master password!!! ergo, you don't have to memorize yet another password, avoiding: the password to access the password used for your passwords.


1) AHK_H allows for some simple protection with some extra work, but it's not very secure. feiyue has a script encryptor which can be a little more secure when used correctly, but it's not perfect either

Now, let's go over the worst-case scenario that will never happen:

  • You use a laptop.
  • Your laptop is stolen.
  • Boot is not password protected.
  • Storage is not encrypted.
  • Windows account doesn't have a password.
  • The robber is well-versed in AHK.

Now, the robber turns on the laptop and goes all the way to the desktop as there is nothing to stop him… then sees that AutoHotkey is installed and that a script is loaded on startup; proceeds to meticulously examine the script and sees that there's a function to type a master password.

You are in serious problems. But for that insecure system, and NOT because you have your master password accessible to the script. In any case, if you have the password encrypted, unless the robber knows the decryption key he won't be able to get the password.

Let's tackle the next possible argument: What if the password is already unencrypted? If the laptop, on top of being this insecure, is taken away by the robber while it is turned on and the robber keeps it like that, then the password is there for the taking… right? At that point, in that ludicrous scenario, is more likely to dump the whole contents of the password manager; again, AHK is not the weak link.

But even accounting for that unrealistic scenario, you can adjust how much time and under which conditions the password is kept in memory with any combination of the following:

  • Manual removal: whenever you feel like it.
  • Computer sleep: when putting the computer to sleep (commute?).
  • Windows Lock Screen: built-in OS locking mechanism (coffee break?).
  • Lid close: if either the computer locks or not (docking station).
  • Inactivity period: not having physical contact with the PC.

So, there you have it; you can actually have your master password accessible to AHK without posing an unnecessary risk.


I'm not gonna add the code/examples here as Reddit lacks syntax highlighting and this much code makes no sense in a post, I rather add the code with examples in a gist alongside a proper encryption/decryption technique that includes key derivation.

I use the password itself as the decryption key to simplify the example, but the data to be encrypted, and the key can be different and of course, it doesn't need to be just a single password. Another example would be to have an encrypted CSV file and the data loaded into an object.

Skip the next section if you know what key derivation is, how it works and how it helps to making brute force attacks harder to success.

If you don't know what key derivation is and how it can help: is a technique used to slow down brute force and dictionary attacks by sequentially deriving your initial encryption key and using not your key, but the derived key of the last iteration; as a result, the decryption process is slower (but only for people that doesn't know the actual key and attempts to brute-force it).

Example:

You have data protected with a 4-digit PIN (please don't), then there are up to 9,999 possible combinations to decrypt it; any modern computer will take less than a second for those 9,999 attempts unless key derivation is used.

Say a key derivation process consisting of 500,000 iterations is used, and it adds a second per attempt. Meaning that instead of cracking the PIN in under one second, it will take up to 2 hours, 46 minutes and 38 seconds: one second for each attempt (if the PIN is actually 9999). Bear in mind that different implementation and hardware have different speeds… 500,000 iterations might not be a whole second, yet it is effectively half a million times slower whatever the speed.

That's why you're encouraged to use long passwords and a big alphabet (ie, lower/upper case with numbers and symbols). The result is that casually trying to decrypt data is not worth the time, effort, and cost (CPU processing is costly). Hence, this is perfectly suited and more than adequate for most people (nuclear launch codes protection not included).

The files in this gist have all that's needed to get the flow I described in the post. To make life easier, I'm using jNizM's AHK_CNG class as it uses BCrypt rather than the CryptoAPI. Plus, it has different output options that simplifies data read/write. With that being said, you can use any method you trust (AGE or GnuPG are other examples).

  • example.ahk: how to use it in your script.
  • Lib\Crypt.ahk: dependency
  • Lib\MasterPassword.ahk: the actual implementation.

For the key derivation, a dynamic salt of the same length of the password is generated. It is also estimated how many derivations can be made in a second, that calculation is then used.

This is not the place to look for security advice, but is relevant to the topic. Also, these tips can be expanded indefinitely and in so many cases are not enough (or too much)… please take them as intended: a reminder that boosting the security of your system doesn't mean extravagances or spending on costly software/hardware, and more especially that security is not exclusively for M.I.B., S.T.A.R., S.H.I.E.L.D., and the likes.

  • BIOS password protection: this is the first line to keep privy eyes from your system (if your household has them).
  • Encrypt your storage: Windows has options to do so (EFS/BitLocker) and if you don't like them or are not available to you, there are free 3rd parties like VeraCrypt or Cryptomator; the latter is awesome with Cloud storage and have mobile options.
  • Password-protect the Windows account: doesn't protect data but has its merits as it doesn't let anyone around to snoop (coworkers trying to prank, for example).
  • Physical and software Firewalls: VPNs are mostly snake oil, properly configured firewalls can be more effective than other networking security solutions. Virtually every modem/router has one, and Window's built-in on whitelist mode is not half-bad.
  • Kensington locks: if your computer can be snatched, why not? Nice when you move around a lot, totally worth it given how cheap they are.

The most beneficial might be storage encryption. With how powerful and fast consumer hardware is nowadays, transparent/on-the-fly encryption is pretty attainable to anyone. Having at least a partition with the personal information encrypted would be my bare minimum. I mean, there's no need to encrypt your multi-TB game library, but personal stuff shouldn't be left in the clear.

Are you really sure it is safe? YES.

If you use only upper/lower, digits, numbers, and symbols a rather common 12-character password with those 94 characters will have the following number of combinations:

106,890,007,738,661,187,092,480 ; Almost 107 sextillions

Meaning a brute force attack needs to go over those, if key derivation is used, well… is just nuts.

But there's more! If also Unicode characters are added, the attack needs to go all the way up to the "Symbols for Legacy Computing" (130,015 characters). I haven't been able to locate a calculator that doesn't generate an error for this absurd number of combinations, the entropy alone is about 466,096 bits (for context, a password entropy of 96 bits is considered "good enough").