# (Or why storing salt (and iterations) alongside hashed passwords is just fine)

Crypto is tricky, so getting your head around all the various bits of key material involved can be challenging. There are quite a number of good resources on this subject. I’ll be referencing various specifications and best practices here - but perhaps someone out there will benefit from my style of explanation.

Specifically, let’s talk about encrypting a Private Key file that we’ll use in some sort of Public Key Infrastructure (PKI). Of which, we’ll need the following components:

## Passphrase

You’re going to need a passphrase: NIST likes to call this a “Memorized Secret“. You might know it as “password”. Whatever you want to call it, this is “Something You Know”. This is the thing that you’re encouraged to create long versions of, perhaps generate randomly and put in a vault such as Bitwarden or LastPass (well, maybe don’t use that one anymore…), so on.

A passphrase must be strong for you to have strong encryption…

I’ll say it again: A passphrase must be strong.

Good techniques for ensuring strong passphrases are actually quite limited though you’ll find many anti-patterns all around you:

• Length: You’ll see recommendations for 8+ characters, perhaps 12 or 16… The longer isn’t necessarily the better depending on your hashing algorithm, but I’m not going to get into the details on that here. It’s fine to think “the longer the better” as a general rule of thumb.
• Checked against top well known passphrase/password lists. Basically you’re going to block out things like “password” (that yes, people really use this all the fucking time in 2023), “Bryan1978” (…oof), etc. Resources are readily available on the web.
• Annnnd… That’s really mostly it. “Must include X” is an anti-pattern. “No longer than Y”. Anti-pattern. Truncating input? Anti-pattern. You’ve seen these everywhere, I know. We can cry together over beers.

💡 You could generate a strong passphrase randomly and stuff it in a vault for extra layers of security. Remember to use a strong passphrase for your vault, too! In Linux you could do something like this: strings /dev/urandom | grep -o '[[:print:]]' | head -n 32 | tr -d '\n'; echo

## Salt 🧂

A salt is a random value used in conjunction with the input passphrase when hashing. You might see this as “nonce” in various applications. Their purpose? Prevent against repeat (or “replay”, …) attacks (Get the name with ‘nonce’?) What that means is if I have for example pre-generated a big list of passphrase:hash values, and didn’t use the particular salt for a particular passphrase that you did, my list is of no use! It is absolutely best practice to generate a new salt for a given passphrase. And, when the salt is sufficient in it’s length and randomly generated, the chance that I have hashed passphrases with the same salt as you are, well up to the length (again!) and I suppose the RNG gods.

Hot damn, we’re on the topic a key reason for this post… salt storage! This is where it get’s a little more confusing. The salt is not considered a secret. Do you want to paste on the Internet? Probably no, but actually you could with little fear. But don’t take my word for it.

As discussed above, the salt is to prevent repeat attacks. But the salt is also required to decrypt encrypted material or come up with a matching hash given a passphrase. It is true that given the salt, an attacker can attempt to brute force your passphrase. However, the power is not in the salt. It’s the length of your passphrase covered above. Is life a little easier for an attacker if they know my salt? Actually yeah a little. The problem is however, it’s needed to decrypt. So anywhere validation/decryption occurs the salt needs to be known “in plain text” (or in raw decimal, or whatever you use). In other words, if the attacker can get their paws on your hashes, they can get their paws on your salts. It’s fine though. Don’t care about that. What we don’t want them to have is your strong passphrase.

Often, we don’t even have a choice! Let’s look at a concrete example – Encrypting a Private Key file we plan on using for certificate signing. If you’re not up on it, it’s OK. Quick explanation: A Private Key is in a way, a super duper long version of a passphrase. It’s what actually is used to encrypt data. What if a bad actor gets their hands on a Private Key? Ouch! They are now able to represent themselves (when certificate signing) as you! So let’s protect it a bit by encrypting the Private Key! Now if CptBaddiePants gets their hands on your MySigningPrivateKey.pem, they’re going to need “Something You Know” to do decrypt and use it. Hey, it’s that passphrase thing!

But guess what else you need to know to decrypt your private key? The salt that was used with it (and, depending on the algorithm, the iterations… I’ll touch on them a bit later). Now, if we expect you to have to keep track of the salt, what does that smell like? If you’re following along, it will smell an awful lot like just another password. That’s certainly not very helpful. See where this is going? We’re going to need to put it with the encrypted private key file so it can be of any use. But remember: This is OK!.

Cool, so a quick run through using OpenSSL for you to actually do the needful. In this case, we’ll create a ECDSA P-256 (in which you may see referred to as names like “secp256r1” or “prime256v1”) Private Key, then encrypt it with AES-256-CBC.

See the line there with the encryption info? Guess what?

DEK-Info: AES-256-CBC,A5DB8977466F0618E69828745C4A4B43

Whao now bro, you’re storing my salt… But I’m not mad!

If I want to decrypt and use the PrivateKey.pem file above, I need what matters: My passphrase. Hopefully I used a good one!

💡OpenSSL will not require a strong passphrase! That’s left up to the user. Better not make it “password” though, because that’s in my list ☺

Let’s look at another example, a Linux /etc/shadow file. The format is roughly this:

Until next time…