Florent Daigniere writes:

> On Thu, 2016-12-22 at 11:22 +0100, Arne Babenhauserheide wrote:
>> > >  Is it somehow possible to decrypt parts of
>> > > the store at random in the hope of hitting a random uploaded
>> > > private
>> > > key
>> > > (a variant of the birthday attack against the password which would
>> > > avoid
>> > > having to query the network for each check)?
>> > > 
>> > 
>> > Of course it is. Your scheme is completely broken; at the very least
>> > the
>> > "passphrase" should be salted, hashed and iterated... and yes, that
>> > means getting the user to remember the salt too.
>> 
>> The passphrase must be as strong as would be needed for passphrase
>> plus salt.
>> 
>> For hashing and iterating: Is that of practical utility when I’m
>> sticking the password into a KSK in the end? Isn’t the cost of
>> attacking
>> the KSK much higher than the cost of hashing and iterating?
>> 
>> (this is my core question here: what’s the cost of attacking a
>> randomly generated KSK?)
>
> The answer is in src/freenet/keys/ClientKSK.java
>
> It's designed to be fast, not secure... so unless you iterate it, I
> think that it is madness.

I think I see how to address that (described in the next paragraph). But
for the sake of sharing better practices than what I used, this is what
I got wrong:

- The decryption keys of WoT IDs have to be considered public knowledge,
  so anything uploaded to USK@…/ can be attacked offline by trying to
  decrypt locally stored chunks.
- KSK does actually hash and iterate, but it is designed to be fast,
  therefore the keys must be very long to avoid rainbow-table attacks,
  and whatever is used in a KSK in large quantities must be iterated to
  increase the cost of offline attacks on whatever the node has in
  store. A salt could avoid that.


I think the following improved design should address the issues:

- The recovery secret will be of the format <creation year>/<part1>/<part2>
  with part1 having about 45 bits and part2 having about 100 bits of entropy.
- Recovery works in four steps:
  - Retrieve KSK@<prefix><part1>--wotid. This contains <name>@<WoT ID>
  - Use pbkdf2_sha256 from passlib[1] with <part2> as key and the 
    <WoT ID> as salt to generate a secret with sufficient iterations to
    make en-masse local storage decryption attacks infeasible. This
    gives <salted-secret> 
  - Retrieve KSK@<prefix><salted-secret>--insertkey. Use it as <insertkey>
  - (Re-)create the WoT ID using <name> and <insertkey>.

Example recovery secret:

    2016/c1n8-83cE/aRUk*DDWL+4Sps_1LgM


Do you see remaining problems with the scheme?

(the security of the 45bit part1 only need to suffice to make accidental
collisions sufficiently unlikely. The WoT ID as salt should be
considered public knowledge)


Best wishes,
Arne

[1]: See https://passlib.readthedocs.io/en/stable/
     and https://www.public 
keyberciti.biz/python-tutorials/securely-hash-passwords-in-python/
     pbkdf2 is the only algorithm in there which does not require
     shipping compiled code, therefore I cannot use one of the stronger
     methods like argon2 or bcrypt.
_______________________________________________
Devl mailing list
Devl@freenetproject.org
https://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl

Reply via email to