Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2010/08/05

More on Passwords

In the comments of a previous post on creating passwords, xenoterracide mentioned his method of creating more secure passwords.

I say "more secure" rather than secure because, as mentioned in an exchange in xeno's comments section that got so heated xeno locked the comments, the entropy could be better, plus if the desire for the passworded information gets big enough, they'll just use legal or extralegal methods rather than crack your password. Basically, we're trying to make it easier to have passwords that are better than average.

The Xeno method is as follows.

echo -n SOME_STRING_YOU_WILL_REMEMBER | sum | base64 

or

echo -n SOME_STRING_YOU_WILL_REMEMBER | sha1sum | base64 

I wrote code to automate it somewhat. I display the hexdigest and base64 digest of the string.

#!/usr/bin/perl

# turns the input into a string and puts out SHA1 digests in both hex and base64

use 5.010 ;
use strict ;
use warnings ;
use Digest::SHA1 ;

my $sha = Digest::SHA1->new;
$sha->add( lc join ' ' , @ARGV ) ;
say $sha->hexdigest;
say $sha->b64digest; 

But I have realized a problem with this. Let me give you the use case.

You have otherwise had your account hacked. You do this on a machine where someone else has root, or you have an ancient version of sendmail or you use .authorized_keys and someone came in free from another machine. They don't need to be root, they just need to be you.

grep password .bash_history
grep sha1sum .bash_history

So, writing it up as a tool that takes the string from STDIN while running, not from the command line so it ends up in the .history, that's how it should be.

I haven't written it up like that yet, but it should be easy. I mean, the above example is only 4 lines of real code, right?

12 comments:

  1. There's a bug in your code. Try running it:

    $ seq 1 10 | xargs -i perl sha1.pl {}
    356a192b7913b04c54574d18c28d46e6395428ab
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    da4b9237bacccdf19c0760cab7aec4a8359010b0
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    77de68daecd823babbb58edb1c8e14d7106e83bb
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    1b6453892473a467d07372d45eb05abc2031647a
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    c1dfd96eea8cc2b62785275bca38ac261256e278
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    902ba3cda1883801594b6e1b452790cc53948fda
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    0ade7c2cf97f75d009975f4d720d1fa6c19f4897
    2jmj7l5rSw0yVb/vlWAYkK/YBwk
    b1d5781111d84f7b3fe45a0852e59758cd7a87e5
    2jmj7l5rSw0yVb/vlWAYkK/YBwk

    See that? The Base64 is same thing.

    The perldoc says:

    Note that the "digest" operation is effectively a destructive, read-once operation. Once it has been performed, the "Digest::SHA1" object is automatically "reset" and can be used to calculate another digest value. Call $sha1->clone->digest if you want to calculate the digest without reseting the digest state.

    So you have to add it again.
    $sha->add( lc join ' ' , @ARGV ) ;
    say $sha->b64digest;

    Your blog post's perl code is a great improvement over xenoterracide's post because instead of base64ing an ascii hex digit sequence, you base64 a uniformly random binary string (a sha1sum). This string has way more information in it.

    64 characters picked uniformly randomly (a..z,A..Z,0..9,+,/):
    $perl -e 'use v5.10; @a=("a".."z","A".."Z",0..9,"+","/"); for (1..1000) { say (map { $a[rand(@a)] } (1..8)).$/ }' | ent
    Entropy = 5.832716 bits per byte.



    # using a modified sha1.pl with the above bug fix and the hex digest removed
    $ seq 1 1000 | xargs -i perl sha1.pl {} | cut -c 1-8 | ent
    Entropy = 5.831898 bits per byte.

    Remember that an increase in entropy is an exponential increase. Also that ent is counting the newlines here. So this entropy is far better than the 5.13 entropy from xenoterricide's post. In fact it is almost 16X better.

    Anyways by using sha1 digest's own base64 you effectively uniformly smear the sha1sum across the alphabet you are using (base64 (a..zA..Z0..9+/)) because you're base64ing binary data that is uniformly distributed across the entire range of bytes where as base64ing hex digits is base64 across a range of 16 different bytes, not a large range at all.

    An improvement would be to extend the characters you use for a password and then do your own base conversion.

    ReplyDelete
  2. Interesting. Normally I use hashing/digests like this in non-security-specific applications, like "are these two MP3s the same song?" and thus haven't gotten too deeply into the issue. Thanks for the comment. I will meditate on that and poke my code later.

    ReplyDelete
  3. You should salt your hash. You can do this by adding a secret to your input string. You could even ask for the secret every time such that you could have your secret key scheme.

    ReplyDelete
  4. re: Salt. That is a good idea. It certainly keeps it from being easily rainbow-tabled.

    ReplyDelete
  5. I've never once suggested this should be the final hash stored in the database. The final hash stored in say... /etc/shadow is salted.

    And according to randomness-is-godlike it would take ~$12k over 2months? to crack my salted sha512's even knowing the algorithm...

    also you can delete lines from your history easily, and I've said you should add memorable characters to the output, which means they'd just have the majority of your password if they got it, and they wouldn't necessarily know how much of it to use, or what part. Also you don't have to generate the base on the system you're using it on.

    I'm not convinced that there's an attack that can executed on an other wise properly secured system. It's much easier to grab my password from pidgin than to crack it, or use a packet sniffer because so much is transmitted in plain text. God knows how many sites store passwords in plain text or unsalted hashes. Hell how many sites limit the attempts to log in, or at least throttle them... the problem is not how weak, or not weak my passwords are, the problem is all the other security vulnerabilities.

    ReplyDelete
  6. I do want to mention one other thing... when I was ~20 I cracked a... 14? year old boys password by hand in ~10 tries... and by hand I mean by typing it in. His hint was "what girls are". This kind of weak password is what I'm trying to prevent people from creating. I've seen my gf's password, believe me there are way too many that will fall to a dictionary attack.

    ReplyDelete
  7. Hey, guys? Guess how interested I am in having this thread be the home of continued discord between r<=>g and xeno?

    I don't believe that someone can get into my work box. But I believe that my work box would be more secure than it is now if I had a stronger belief/paranoia about it's insecurity. I was told by datacenter types about a recent attack that hit via the authorized keys vector, where the attackers then tried to replace sshd, only to have it get replaced back by cfengine, and the reason anyone knew was the explosion of logs saying "I re-installed SSH-server". Not to mention the idea that if they get physical access to your computer, it's all theirs anyway. Thinking "to what extent am I still safe if they break in or my admin goes rogue" isn't a bad thing.

    One other story. About 10 years or so ago, I had a friend who was a grad student. He stayed in an office with three others, each with a Linux box running KDE. We were sitting, talking, when the idea of buffer overflows came up. So, I held down the "F" key for a few minutes, then hit enter. The screen saver crashed and I was in. I know that I can't do that to my Gnome screensaver right now, but it would not surprise me if there were other things beyond plugging the liveCD-on-thumbdrive into the USB port that would crack it wide open, making my passwords moot.

    xeno and I (Is it alright if I call you xeno?) are mostly concerned about raising the low end, getting people off dumbass passwords. From the first comment here, I see the full hex output on the string "1" would be "356a192b7913b04c54574d18c28d46e6395428ab". I know pi up to 3.14159, so I'm sure I could keep 356a192b in my head without a lot of work, and if I have Google Chrome save my passwords and know I can always re-generate it, why not have my bank password be "356a192b7913b04c54574d18c28d46e6395428ab"?

    And r<=>g? It seems like I'd be enshrining my secrets in code the more I reread the Salt comment. That is, if I misread it. If I don't misread it, well, assuming the stored salted password is "oldpassword", I'd grab "ol" to be the salt for the new password. When I type "passwd" into the command line, passwd handles the salt for me, but where's gen_password_re.pl going to grab the salt if all it is doing is giving me a string I'm going to mentally cut down to 10 characters and type into the password field of a website?

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. This was posted to Hacker news. http://howsecureismypassword.net/

    I don't actually know if it's any good...

    ReplyDelete
  11. Not sure I'd want to put a password I'd actually use into that.

    ReplyDelete
  12. I have looked at that page, and it is all Javascript with no talk-back to the server.

    ReplyDelete