
Midnight project: Password manager without a password manager - jaseg
https://gist.github.com/3334991
======
anon081312
I think this is catastrophically broken because of a known issue of how SHA-2
breaks its input into blocks: when A is aligned to a block boundary, sha(A ||
B) = f(sha(A), g(B)).

[http://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_con...](http://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction)

In your system, the derived password is a sha digest of a concatentation of
other sha digests. It _almost_ has the form sha(sha(SALT) || sha(RESOURCE) ||
sha(MASTER)), with sha() returning the ascii encoding of the base-16
representation. (The difference is three extra newline characters "\n", which
makes things slightly messier). This string representation for sha-512 digests
is 128 characters or 1028 bits, and sha-512 uses 1028-bit input chunks, so the
final sha() call reads the other three digests aligned on chunk boundaries.
(Again, few bits off because of newlines, but this is not fatal).

So DERIVED(RESOURCE) has a form

    
    
        DERIVED = sha(sha(SALT) || sha(RESOURCE) || sha(MASTER))
                = f(sha(sha(SALT) || sha(RESOURCE)), g(sha(MASTER)))
    

where f,g, are known functions. Moreover, f is reversible -- in SHA-512 it is
just addition.

So for an attack: given the salt, along with one resource/derived password
pair, every other password can be computed. If you know SALT, RESOURCE_1, and
DERIVED_1, you know these:

    
    
        sha(sha(SALT) || sha(RESOURCE_1))
    
        DERIVED_1 = f(sha(sha(SALT) || sha(RESOURCE_1)), g(sha(MASTER)))
    

Because f is reversible, and you know its first argument, you also learn its
other argument,

    
    
        g(sha(MASTER))
    

and can calculate any other password, given the resource name. Note you don't
learn the master password, nor its sha digest -- you can't reverse the block
function g(), not without breaking SHA-2 itself. But that's not necessary.

~~~
dexen
_> I think this is catastrophically broken because of a known issue of how
SHA-2 breaks its input into blocks: when A is aligned to a block boundary,
sha(A || B) = f(sha(A), g(B))._

If that's the case, wouldn't it suffice to mix A and B, for example with byte-
wise XOR?

    
    
      password ::= sha(A XOR B)

~~~
jaseg
Though that would be hard to do in a one-line shell script, which was the idea
behind the gist.

------
antimora
This approach is cryptographically WEAKER than a password manager!

Because password[0], password[1], ... password[n] are all related through
common salt and master password string (and known domain name). Where as
passwords stored in a password managers are independent.

Therefore, in theory, if I know a few of your passwords (lets say I own 10 top
domains and you've got accounts with me), I can crack your salt and password
file, or at least, I can generate probable passwords for other domains.

~~~
cwp
Also, the advantage of not having to keep your password database secret is
negated by problem of keeping your salt file secret.

~~~
gizzlon
Since when is your salt suppose to be secret?

~~~
pwg
>Since when is your salt suppose to be secret?

In the instance of this particular algorithm, the salt must be kept secret,
because it is the only unknown in the process from an attackers point of view.

~~~
icebraining
Not true, you have to input a master password (it's what the ';sha512sum -'
part does), which is also unknown to the attacker.

~~~
pwg
Fair enough, but then the "salt" is not really a "salt" anymore as that term
is known from "password salt", because it is no longer a random input value
unique to each different password. It is simply a piece of known-plaintext
input for every "hashing" session.

That means that an attacker who can somehow obtain the salt value can now
mount a known-plaintext attack against the outputs of the algorithm.
<http://en.wikipedia.org/wiki/Known-plaintext_attack>

I am ignoring the fact that in a general sense an attacker with resources to
obtain the salt can also likely log the master password, in which case no
attack against the algorithm is necessary.

------
rlpb
You receive an email from a sheepish website owner admitting that your
password has been compromised and asking you to change it. Now what do you do?

~~~
e12e
Add a counter. For a nice discussion on a few of the tradeoffs involved in
such a system as this, see this thread:

[http://www.mail-
archive.com/cryptography@randombit.net/msg02...](http://www.mail-
archive.com/cryptography@randombit.net/msg02875.html)

So for this example, instead of:

    
    
      (sha512sum ~/.salt -<<<www.example.com;sha512sum -)|cut -d\  -f1|sha512sum|cut -c-32
    

eg:

    
    
      (sha512sum ~/.salt -<<<www.example.com0;sha512sum -)|cut -d\  -f1|sha512sum|cut -c-32
    

which can be changed to:

(sha512sum ~/.salt -<<<www.example.com1;sha512sum -)|cut -d\ -f1|sha512sum|cut
-c-32

You can "rediscover" the correct password for a site, relatively easy by using
this method -- iterating up to your current (correct) password. Another
alternative might be using the year or month/year of last password
change/set... all these methods have drawbacks -- but again see the thread for
some interesting points on a similar system.

[edit: typo/formatting]

------
cypherpunks01
I trust Stanford PwdHash (<https://www.pwdhash.com>) a lot more than this, and
it basically does the same thing with some nice features and browser plugins.

------
EGreg
We conceived of something like this for the web a couple years ago, as part of
a much much larger picture:

<http://www.faqs.org/patents/app/20120110469#b>

In our formulation, the salt was simply (a function of) your username.

But yeah, we couldn't find a way to crack it, either.

~~~
pwg
> In our formulation, the salt was simply (a function of) your username.

For password hashing, the input salt needs to be a cryptographically secure
random number. This is because it needs to be unique, and unrelated, to each
password.

In your "formulation", what you have is simply a unique identifier for a user
derived from the three, but it is in no way a "salt" as that term is used in
regards to "salted passwords".

> But yeah, we couldn't find a way to crack it, either.

Just because you couldn't find a way to crack it, does not mean it is secure:

[http://security.stackexchange.com/questions/18197/why-
should...](http://security.stackexchange.com/questions/18197/why-shouldnt-we-
roll-our-own)

~~~
EGreg
on websites, usernames are unique, and they are usually unrelated to passwords

on a related note, we encourage each of our users to select a passphrase, and
even scour yahoo news from the past year, and other sources for three
consecutive words, that the user can easily remember, such as "that truck
driver" or "what he did". This in practice causes users to have a much better
space of possible passwords to begin with ... without which any system would
be susceptible to brute force rainbow table type attacks.

~~~
pwg
>encourage each of our users to select a passphrase, and even scour yahoo news
from the past year, and other sources for three consecutive words, that the
user can easily remember, such as "that truck driver" or "what he did". This
in practice causes users to have a much better space of possible passwords to
begin with

And with a wordlist of the 10,000 most common words, if you are not also using
a key-stretch function (bcrypt, pbkdf2, etc.) all of those examples become
quite trivial to a john-the-ripper ( <http://www.openwall.com/john/> ) type
attack. I.e., a three word phrase consisting of one each of the 10,000 most
common words has at most 10000^3 combinations (1e+12). A 10 digit random
password selected from letters, numbers, punctuation (94 digits) has 94^10
combinations (5e+19). 5e+19 is significantly larger than 1e+12)

~~~
EGreg
In theory, you are correct, of course. In practice, users do not select nearly
close to 5e+19 unique passwords when asked to come up with a "random" password
on their own. And if one is given to them, then it's inconvenient for them to
remember 29c!8z79c. I would rather remember 5 words than 10 random letters,
and 5 words would also equalize the space in your example.

Here is what I am pretty sure is true:

1) The salt just has to be unique enough to make rainbow table attacks on any
significant portion of the userbase infeasible Any given rainbow table will
only work for one salt. From this perspective, usernames are just fine as a
salt.

2) The real danger is password re-use (<http://xkcd.com/792/>) and more
generally, just lousy password selection (know anyone whose password is
"password"?) Pass phrases are better
([http://blogs.technet.com/b/robert_hensing/archive/2004/07/28...](http://blogs.technet.com/b/robert_hensing/archive/2004/07/28/199610.aspx))
and if we can deliver to the users a space of 10^14 possible phrases that
actually sound like they make some sense, as an inspiration for them to choose
a phrase of their own, then I think that's a good thing to do.

3) And of course, we use key strengthening, running the hash function a lot of
times (a prime number of times, just in case ;)

------
greenyoda
One major problem with this scheme is that if someone steals (or subpoenas)
your computer they can discover all your passwords just by looking at your
shell history. A password manager that's secured by a strong password doesn't
have that vulnerability.

Edit: As jroes pointed out below, this is not a problem.

~~~
jroes
They would only discover the domains, not the passwords you entered. You type
the domain at the command line, but you type the password into stdin.

~~~
MTGandP
The program outputs your site-specific password to stdout. Is it possible for
an attacker to get your stdout history?

~~~
lloeki
Might be. Some terminal emulators save logs. "Unlimited scrolling" often goes
to disk, possibly in a file, possibly in swap (Terminal.app makes it stay in
memory, which once consumed 3GB of RAM for my long-lived "rails server" tab).
iTerm2 allows you to navigate back in time, while Terminal.app saves some data
on quit to display on restore (if OSX autosave is enabled).

~~~
jaseg
When you allow less common tools to be used, one could use the bash or zsh
read-builtin to read the master password without echoing (e.g. dash's read can
not do that) and use xclip or similar to directly put the password into the X
clipboard. With xclip's -l option you could even automagically "forget" the
clipboard after it was pasted once.

------
StavrosK
This sounds similar to SuperGenPass, which I've used extensively since I heard
about it.

------
bigbird
Here's a little script that does something similar with some features that
make it more useful (for hackers at any rate):

<https://github.com/jtmaher/Passwords>

------
jayfuerstenberg
This is fine for hackers but for mere mortals it looks cumbersome.

~~~
eps
Mortals simply use domainName+superSecretWord.

~~~
niemand
Shouldn't everyone know by now that this plain text concatenation scheme is
insecure?

By using this scheme, you're trusting $domainName to securely scramble the
password.

Once a single password is known in plain, an attacker has a nice password
template that he can try on any site. The last few bits of security would be
your user name (which is often similar to the one you use elsewhere) or
nothing at all if you can log in by email address (which is usually possible
these days; and that email address is often among the leaked information as
well). Instant login anywhere!

At least hash that '$domain+$masterpass' string...

\-----

More problems: I heard some people still truncate passwords down to
unreasonable lengths on the server side, which might make hash compression
(e.g. base 16 -> base 64) necessary and which will totally break the simple
concatenation scheme, leaving a prefix of $domainName as the actual password.
Ouch.

------
jhawthorn
Similar is <https://www.pwdhash.com/>

~~~
aiiane
Also <http://passwordmaker.org/>

~~~
randomtyler
This /is/ PasswordMaker in infancy. I was a PasswordMaker user for a 3 or 4
years until the project stopped getting updates and they couldn't (or
wouldn't) support Chrome.

