-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Your algorithm is basically okay, but there are a couple of errors you've made, 
things you and I will disagree over, and one flaw that I consider to wreck the 
whole thing. But all of the problems are correctable, easily. If I have not 
understood something, or read it too quickly and gotten confused, I apologize 
in advance.

Let me walk through a reduction of your system:

(1) You take the master password and run it through a 512-bit hash function, 
producing master binary secret.

You pick scrypt for your hash function, because you think burning time and 
space adds to security. I do not. This is a place where gentlepersons can 
disagree, and I really don't expect to convince you that SHA-512 or Skein would 
be better options. I'm convinced that I know why you're doing it, and it would 
be a waste of both our times to go further. We just disagree.

At the end of it, it hardly matters because if an attacker wishes to construct 
a rainbow table, the correct way to do it is to assemble a list of likely 
passwords and just go from there. It will take longer if they use scrypt than 
with a real hash function, but once it's done it is done. They have the rainbow 
table.

This isn't a flaw, it just is. The goal of your system requires that you have a 
master secret. But security-wise, there's no win here other than burning some 
cycles in a way that the attacker can trivially replicate.

Security-wise, I'm quite certain that scrypt isn't nearly as secure as any real 
hash function you'd pick, but I'm just whining. We know that the security is 
password. If they pick "puppies" as their password, it really doesn't matter 
what hash function you run it through. Almost certainly, there is not enough 
security in their password to make it a difference what function you picked.

Let's call the parameters P for password and M for the master key.

(2) You take M and construct site-specific keys. We'll call the site name N, 
your counter C, and the site keys K_s.

You compute a given site-specific key, K_s, with:

K_s = SHA1(S + M + C), where "+" is the function that concatenates a null byte 
and then the second string.

Strictly speaking, you really ought to do it in the order K + C + S, because 
that's more collision-resistant. It's good practice when computing a keyed hash 
to hash the key first. In reality, it probably doesn't matter, but it *does* 
save you lots of debates with people like me.

You also want to hash in the length of S, too, because that's also more 
collision-resistent.

So you really want it to be K_s = SHA1(M + C + S.length + S), but that's the 
only real security problems I can see. The ordering is a nit, and omitting the 
length is only a problem if the hash function is broken. Speaking of which, why 
not use a non-broken hash function, like SHA256, or SHA512 or SHA512/160, if 
the output size matters to you? Given that you're using scrypt, why not use a 
better hash function, even if it is slower? But that's also a nit.

The real problem you have, however, is in the counter. First of all a counter 
is not a salt. A salt is an arbitrary non-security parameter. But arbitrary 
means random, just not secret. A counter is a counter.

The counter has two problems to it. One is that it doesn't add to the security 
of the system. The other it makes system utterly useless. 

An attacker can easily brute force through the site keys by just running a 
counter. That's why I say it doesn't add to the security. Even if you used 
scrypt here, too, it wouldn't matter much. It's still easy to brute force.

However, this completely ruins the system for the end user. The end user can't 
just remember their master password and the site name. They have to remember 
what *order* they did it in too, which ruins everything. You can't sync this 
across devices, you have to keep track of orders, and so on. You need to remove 
the counter.

I understand why you did it. You did it because that way two people with the 
same master password on the same site aren't going to have the same password -- 
which would give away the master password to the other one, as well as leaking 
to an attacker that you picked a lousy password, even if they don't immediately 
know what it is (cue the rainbow tables). Ironically, this is kinda like the 
recent RSA/GCD thing in that your security oops can be made into a disaster if 
someone else makes the same oops.

You can fix this one by substituting the person's site username for the 
counter. In this revision, you have K_s = HASH(M + U.length + U + S.length + 
S). That's a much better construction.

(3) You run the site key, K, through some pretty printer. I really didn't read 
this and really don't care. It doesn't matter to me. TL;DR.

All in all, it's cute. I like it enough to write this note. I advise that you:

* Pick a real hash function or two. We can debate scrypt, but you can do better 
than SHA1. Even a second scrypt is better than SHA1. Maybe.

* Get rid of the counter. It ruins everything you were trying to do. You really 
do want this to just be F(M,U,S).

* Use the construction I ended up with above: K_s = HASH(M + U.length + U + 
S.length + S).

        Jon


-----BEGIN PGP SIGNATURE-----
Version: PGP Universal 3.2.0 (Build 1672)
Charset: us-ascii

wj8DBQFPxc0esTedWZOD3gYRAtaXAKDcdgie3Yy8virTGsYc+CzSSpG03gCgjMVx
UlVm68mcxjfkH08smq6J2jw=
=akXu
-----END PGP SIGNATURE-----
_______________________________________________
cryptography mailing list
[email protected]
http://lists.randombit.net/mailman/listinfo/cryptography

Reply via email to