top of page
Christopher Bradford

Password encryption: Real talk and why it matters

Updated: Mar 22, 2022



Data breaches are costing companies more money each year. A study, published by IBM Security, reported the average cost of a data breach at $4.24m with 20% of data breaches due to compromised credentials. Due to the high cost and high probability of a data breach being caused by compromised credentials, credential security is of paramount importance to maintaining a company’s finances and brand image.


Actual company name has been redacted for privacy.

It’s been found that the [company] application is currently using outdated methods to secure user credentials. Passwords are currently salted and encrypted, but that isn’t enough to prevent a data breach in today’s world. This document should serve as a quick reference as to why encryption isn’t enough and what actions can be taken to enhance [company]'s credential security.


Why Shouldn’t You Encrypt Passwords?

Encryption is considered a two-way function. These two functions being encryption and decryption. Part of an encryption’s security comes from the need to use a key to allow for decryption. This usage of a key is what makes it undesirable as a password security method as it makes encryption reversible. If the key is compromised, decryption allows for password recovery in plaintext and without guessing.


The encryption key also requires maintenance and secure storage - adding to the already complex rules and configuration of an application. If an attacker were to gain access to the source code and gain access to the database, they would have access to all user passwords - and you should always work under the assumption that your code and/or database will be compromised.


Why Should You Hash Your Passwords?

Besides being recommended by NIST and OWASP, hashing is considered superior to encryption as it is a one-way function, and the plaintext password cannot be obtained by reversing the hash. After hashing, the password is stored as a fixed-length “fingerprint” of sorts. This “fingerprint” is great for security as it allows for protection of the password even if the codebase and/or database are compromised and still allows us to ensure a user’s password is correct.


Not All hashes Are Equally Secure

A good hashing algorithm should be slow and cryptographically secure. Although slow sounds like the opposite of what we’d want when considering application performance, “slow” roughly correlates to the speed in which the hash can be cracked.


Argon2id, bcrypt, scrypt, PBKDF2 are considered the most secure hashing algorithms to use as of 2021 as they have been designed to securely store passwords and have a configurable work factor.


Slow Hashes and Work Factors

Computer hardware is more powerful than ever, and Moore’s law ensures that it will only become more powerful year after year. This hardware can be used to perform dictionary or brute-force attacks - computing billions of hashes per second. To help mitigate these attacks, the recommended hashing algorithms have a configurable work factor (also known as an iteration count). The work factor is the number of hashing iterations performed for each password - the higher the work factor, the more computationally intensive it is to calculate the hash. A higher computational cost means a reduction in speed for an attacker trying to crack a password hash or an increase in the resources an attacker needs to try and crack the hash.


A work factor needs to be carefully considered though. Ideally one would configure the work factor of a hashing algorithm to its highest value to impede an attacker’s performance but doing so would also make verifying login attempts slower for the end user. A balance must be found between security and application performance. The password hashing should be slow enough to ward off attacks, but fast enough as to not degrade the user’s experience. This balance of speed vs. security will be determined by the performance of the server, the number of application users, and the maximum rate at which authentication is requested. One second or less is generally considered the optimal time it should take to calculate a hash.


Using Salt for More Secure Hashes

Although hashing a password is more secure than encryption for security, there are still vulnerabilities. Lookup tables, reverse lookup tables, and rainbow tables are the common ways to crack password hashes, but salting makes it significantly more difficult.


A salt is a randomly generated, unique string that can be prepended or appended to the plaintext password before hashing. Using a salt means that two passwords that are the same in plaintext will never have the same hash since a unique string was added to it. The salt doesn’t have to be treated as any kind of secret either. It is usually stored alongside the password hash to be used for authentication.


Salts are only effective when implemented correctly. Salts should always be unique per user (when creating and changing a password) and should always be long and cryptographically secure. APIs provided by languages to create random strings (like the NewGUID method in .NET) may look like a way to generate a secure, random number but have a level of predictability as they are created using a “standard” set of instructions. In order to create a unique, long, and cryptographically secure salt, a cryptographically secure pseudorandom number generator (CSPRNG) should be used. CSPRNGs are designed to generate a high level of randomness and unpredictability.


Current State

  • Salts are currently created in LQMS.ServiceLayer UserBL().GetSalt() generating Guid.NewGuid().ToString()

  • Passwords are encrypted and decrypted in LQMS.Common EncryptionProvider

  • The EncryptionProvider uses the managed version of the Rijndael algorithm from System.Security.Cryptography

  • The key is a byte[] converted from a hardcoded base 64 string

  • The initialization vector is a byte[] converted from a hardcoded base 64 string

  • The salt is stored in the users table

  • The encrypted password is stored in the users table


Issues

  • Salts are not generated using a CSPRNG

  • Passwords are encrypted instead of hashed

  • Even if encryption were okay to be used, the key and IV haven’t been changed/rotated and aren’t stored securely

  • Rijndael encryption (aka AES) has known attacks


Ideal State

  • Salts would be generated using a CSPRNG like System.Security.Cryptography.RNGCryptoServiceProvider

  • Salt would be prepended to the plaintext password

  • Salt + Password would be hashed using System.Web.Helpers.Crypto with an acceptable work factor

    • This Crypto class uses PBKDF2 with HMAC-SHA1 and is provided by Microsoft

In architecting the new solution:

  • An Authentication/UserAuthentication service can be created that solely handles authenticating users

  • Create a class for hashing and verifying hashed passwords

  • Create a class for validating password rules (should be uppercase, should have x number of characters, etc.)

  • Create a class for a login response (success, errors, failures)


Moving Existing Users to the New Hashing Algorithm

There are numerous options for upgrading the users to use the new hashing algorithm with the key differences being how convenient it is for the user:

  • Require all users to reset their password

  • Require users on a client-by-client basis to reset their password

  • Re-hash passwords using the new algorithm the next time the user logs in

  • Re-hash all passwords at once using a batch job

Sources:














Commenti


© 2018-2023 By Kristen Swearingen - swearingen.me | MiddleChild Tech | eruditeMETA. All rights reserved.

This publication may not be reproduced or distributed in any form with the author's prior written permission. It consists of opinions of the author's research and experience, which should not be construed as statements of fact. While the information contained in this publication has been created and cited where obtained from sources believed to be reliable, the author disclaims all warranties as to the accuracy, completeness, or adequacy of such information. Although this post and cited research may address legal and financial issues, the author does not provide legal or investment advice and its publication should not be construed as such. Your access and use of this publication is governed by the Usage Policy for swearingen.me | MiddleChild Tech | eruditeMETA,, respectively. The author prides his/her/their self on his/her/their reputation for independence and objectivity. The research and publication(s) are produced independently by its authors and organization without input or influence from any third party. For further information, see the Guiding Principles on Independence and Objectivity.

bottom of page