It's well understood that developers, and especially line-of-business developers, spend much more time reading and understanding existing code than writing new code. Yet one of the most common interview approaches emphasises writing new code.
So one of my standard developer interview questions is to give the candidate a few lines of rather dodgy code and ask the following:
- Explain what the code is doing.
- Explain any significant issues with the code.
- Explain how to prioritise the issues.
- Explain how to fix the issues.
After some reader feedback and a real-life deployment, I've re-factored the password utilities library to be more functional, easier to use, and more maintainable. This has enabled the following improvements:
- The ability to define and use any combination of the default and custom character sets when generating passwords. There are six default character sets covering the normal ASCII range. You can define as many custom character sets as you wish, with the caveat that the current code allows passwords to be generated from a maximum of 255 unique characters.
- The ability to encode all of the hash information needed to verify the associated password at a later stage. This includes the hash algorithm (SHA1-160, SHA2-256, SHA3-512, BCRYPT-192, or SCRYPT-512), the salt/hash encoding format (HEX or BASE64), the work factor (number of hash iterations), the encoded password salt, and the encoded password hash. This information is returned in a printable ASCII string that can be stored in a database or other location.
- An interactive Windows Forms user interface that demonstrates most of the library's capabilities.
- Some usability and library interface improvements along with a couple of bug fixes.
Before demonstrating the new password utilities library, we interrupt our scheduled programming to bring you the latest offender in end-user personal data storage. Sony's Playstation Network and Qriocity services have recently suffered a major intrusion that exposed personal data for its 77 million users. It's not completely clear from their FAQs, but it appears that the user passwords weren't hashed or encrypted, but instead stored in plain text. This makes the Sony rootkit fiasco positively tame in comparison. Read more
The final step is to measure the information entropy of specific passwords and their hashes. In this context, entropy is a measure of unpredictability. For randomly-generated passwords, the information entropy (measured in bits) is a reasonable proxy for password strength.
For example, a password with 42 bits of entropy is as strong as a string of 42 bits chosen randomly. An attacker would need 242 attempts to exhaust every possibility of finding this password by brute force. Adding an extra bit of entropy doubles the number of guesses required, making the attacker's task twice as difficult.Read more
To create the salted hash, we're going to use the .NET Framework's implementation of a key derivation function called PBKDF2, also published as RFC 2898. PBKDF2 has some useful properties: you can use a salt, you can define the hash output size, and you can configure the slowdown factor by specifying the number of iterations over the hash function. Read more
Hashing a password involves a one-way function that converts an (optionally salted) password into a fixed-size set of bits. The idea is that you always store the password hashes rather than the passwords themselves. After storing a password hash, you can then verify the associated password, by hashing it and then comparing with the stored hash. Read more
Now that we have a PasswordPolicy class and a Die class, the actual password generation process is very straightforward.
We first need to know the password policy, and then roll a die which has the same number of sides as the number of symbols in the policy's acceptable symbols list. The roll result is used as an index into the symbols list, and the symbol at that position becomes the next character in the password. Repeat for as many characters as the password needs - again, this is defined by the password policy.Read more
The term "pseudo-random", as used by cryptographers, may be misleading to a non-technical reader. Numerous important systems, ranging from military communications to the encryption that protects virtually all online transactions, rely on the functionally-equivalent security between "cryptographically-secure pseudo-random" and "random". Read more
Most applications that use a password or passphrase for user authentication also have a policy that dictates the password complexity requirements. These requirements range from a simple minimum length to some very complex rules. There's a decent case for arguing that the more complex policies might actually reduce security in some circumstances. This is because these policies encourage users to invent easier-to-remember (i.e. weaker) passwords or to write down passwords in order to remember them. Read more
Imagine that your website's password database has been compromised and is in the hands of the attacker. He can launch an offline attack on the database, and dump your users' account names and cracked passwords publicly on the Internet. At this point, you have 4 potential problems:
- Many of your users will lose trust in your organisation.
- Your organisation will have some unpleasant publicity.
- The dump can be harvested by people looking to compromise your application's users.
- The dump can be harvested by people looking for passwords that might have been reused on other web sites.
So you're now in a race against time.Read more