7

I would like to implement a password creating program, similar to ones provided by Symantec and LastPass. This program will allow the user to simply specify different password lengths and options.

Are there any security considerations that should be made aside from using a proper cryptographically secure pseudo-random number generator in the algorithms? My plan was to use something like the RNGCryptoServiceProvider . "Secure random password generator" means one that is at least not backdoored or susceptible to frivolous flaws due to improper implementation. This is not a networked application.

Please note: I have no intention of "rolling my own" crypto or hashing.

the_endian
  • 1,009
  • 1
  • 8
  • 17
  • This is pretty much the textbook definition of rolling your own crypto[system]. As Thomas Ptacek put it, [if you go into it thinking that the dangerous stuff is in the primitives like the AES core, and if you just stick to the glue you'll be safe, you're gonna have a bad time](https://news.ycombinator.com/item?id=5104047). If you have to ask this question, you are *not qualified* to be distributing this kind of software. So by all means, please build to your heart's content for the sake of learning. But *please* don't release this software or otherwise distribute it to others. – Stephen Touset Mar 13 '17 at 17:57
  • Did I say I'd be releasing it? And resources to where I can "get more qualified" would be great because right now your comment is a little cryptic. Should I study more cryptography? Networking? Etc... there's not much value offered in terms of real world advice here other than just "don't do it" which isn't really advice honestly. – the_endian Mar 13 '17 at 18:01
  • This is just a standard disclaimer — only so much fits into a comment. Many, many people come here to get basic crypto questions answered in order to build something that they intend to release to the public, without understanding that there are as many traps involved in designing and implementing a system as there are in building cryptographic primitives. – Stephen Touset Mar 13 '17 at 18:04
  • 1
    Ok, well, that makes sense. Apologize if I was a little short-sighted in that regard as this Q will likely be viewed but many people in the future. Anyways, definitely don't worry about me, I'm a malware researcher and won't be releasing insecure products anytime soon :) – the_endian Mar 13 '17 at 18:07
  • 3
    I disagree with @StephenTouset that this is the "textbook definition" of rolling your own crypto. Random password generation can't be compared to inventing your own hashing algorithm. – Arminius Mar 13 '17 at 18:19
  • "Implementing a password creating program… similar to… Symantec and LastPass" is a dramatically larger problem than merely the generation of random passwords. You have to store those passwords, and that needs to be done safely. You need to store metadata — sometimes searchably (and in some cases prior to unlocking the keyring), and that needs to be done safely, too. For a non-toy app, there's browser integration, paste buffer management, and a dozen other things to worry about. This is literally OP's question: "What else of security concern is there?" and the TL;DR answer is "a lot". – Stephen Touset Mar 13 '17 at 18:42
  • 2
    @StephenTouset From my understanding, OP is only interested in the password *generation* part, not storage, not distribution. An own password manager is obviously a different story. – Arminius Mar 13 '17 at 22:08
  • 1
    Yes I didn't mean a full scale application, im just talking about a generator here. I did mention it's not a networked application and that I wasn't planning on inventing any new crypto algorithms. I'm simply talking about generating some password strings. In fact, storage or transfer is not part of this at all. – the_endian Mar 13 '17 at 22:10
  • 1
    There are many open source password generators you could get the source for like pwgen, the generator in keypass and so on, which should give you a good starting point – Zoredache Mar 14 '17 at 00:40
  • 1
    The password generation itself is trivial, the entropy is not. My passgen (just a perlscript) runs a for-loop up to the specified length, including various charsets, depending on cli options. I do re-seed from random device (although perl does this automatically), but I doubt I have ultrahigh entropy. I've heard of people seeding their PRNG with microphones, accelerometers, seismic sensors, and other fun. – user400344 Mar 14 '17 at 09:48

2 Answers2

6

Creating a secure password generator is fairly easy, provided you have two components:

  1. A cryptographically secure RNG. This means the output of the RNG is a bit stream that must not be predictable under any conditions. In most cases however, you can just use a PRNG designed specifically for key generation like /dev/urandom, /dev/random, or CryptGenRandom. Regular PRNG like Mersenne Twister should not be used for key generation. You should not attempt to write your own CSPRNG unless you have a deep background in CSPRNG mathematics. This is the part where most "regular people developing password generators" often don't really pay enough attention to.

  2. A one-to-one encoding algorithm. This algorithm encodes the bit stream produced by the RNG into something acceptable by the system that needs to use the password and, for memorizable password, the preference of the user. A one-to-one encoding is a function that does not have any output collisions for its inputs, so a the function does not lose any entropy produced by the RNG during the encoding. This is the part that is actually extremely easy, but most "regular people developing password generators" often overcomplicate unnecessarily, and end up weakening their password generation method.

Example of one-to-one encoding algorithm: Diceware, base64, hex encoding, any perfect hash function. Example of transformation algorithm not suitable for password generation: most regular hash algorithm.

Once you have these two components, all you need to do is ask the CSPRNG for a bit stream of length n, where n is the required strength of your password, and encode that bitstream using your selected encoding algorithm.

Pitfall: You should parameterize the encoding algorithm so it can never produce a password that would be rejected by the target system's password policy. If you simply reject a password and generate it again using different random value, you are reducing the entropy. In theory, this does mean that you will need to know the exact password policy detail of each system you need to generate for to correctly calculate your password strength. In practice, you can often simply add a few more bit strength to compensate for the entropy loss due to such overcomplicated password policy.

Pitfall: For memorizable passwords, the user must be trained not to reject any password that they end up finding hard to memorize as this also reduces the entropy. This means that memorizable password encoder should be designed as much as possible so that it produces passwords/paraphrases that's most likely to be accepted by the user in the first try. There are few encoding algorithms that attempts this, for example EFF Diceware wordlist or Grammatical Diceware.

Lie Ryan
  • 31,089
  • 6
  • 68
  • 93
  • So, essentially, the algorithm should be designed so that whatever the CSPRNG gives us is _fully accepted_ by the system? If there are limitations on what is an acceptable password, then that should ideally be handled as part of the original CSPRNG mechanism rather than taking its output and then further filtering it with non-crypto-secure functions, which would reduce the entropy, thus defeating the purpose of the CSPRNG? ANd if this is not possible, we need a 1 to 1 encoding function which preserves the entropy – the_endian Mar 15 '17 at 03:40
  • No, the role of CSPRNG is to produce an extremely large n-bit number (i.e. a bitstream), where `n` is your password's bit strength. This huge number is your "real" password. The role of the encoding algorithm is to convert that huge number to something you can type, copy paste, possibly memorize, and which the password system could accept. What you want to avoid during encoding is causing entropy losses, which filtering/rejecting inputs and producing rejectable passwords would. You don't need to add entropy in the encoding step as the CSPRNG already produced all the entropy you need. – Lie Ryan Mar 15 '17 at 13:48
  • All this means is that the encoding simply needs to be a one-to-one ([injective](https://en.m.wikipedia.org/wiki/Injective_function)) function, from the CSPRNG output domain to the password system's input domain. It's not the role of the CSPRNG to understand what the password system would accept, the CSPRNG is simply a source of random bits. – Lie Ryan Mar 15 '17 at 13:49
  • Thanks for the link to the new EFF Diceware list. I had been using the old Diceware list to generate passwords for people at work and they were usually too vulgar or too creepy. – browly May 02 '17 at 19:53
2

The principle consideration for a password generator is that it doesn't produce predictable output. The point of random passwords is that the best attack against them is brute force, but if there's a bias, an attacker can take advantage to reduce their search space.

Along similar lines, often people want additional restrictions, like "pronounceable". This can be a security benefit (you can remember passwords instead of storing them) as well as a downside (introducing biases, see above). If you're interested in this, it's important to be very careful about not introducing extra bias into the algorithm, as that's a more complex problem than simply generating random characters.

Xiong Chiamiov
  • 9,384
  • 2
  • 34
  • 76