patrickfav / armadillo

A shared preference implementation for confidential data in Android. Per default uses AES-GCM, BCrypt and HKDF as cryptographic primitives. Uses the concept of device fingerprinting combined with optional user provided passwords and strong password hashes.

Home Page:https://favr.dev/opensource/armadillo

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bcrypt Key Stretcher used incorrectly

patrickfav opened this issue · comments

return Bytes.from(BCrypt.hashpw(String.valueOf(password) + Bytes.wrap(salt).encodeHex(), generateSalt(salt, logRounds))).array();

Unfortunately the jBcrypt API was used totally incorrectly (to be fair, the API does not have any fail safes to warn the user):

  1. The password is encoded with hex and the salt is appended:
    String.valueOf(password) + Bytes.wrap(salt).encodeHex()
    First of all, I dont't know why I appended the salt. Second, bcrypt only supports 72 bytes of PW by encoding the UTF-8 byte array as hex the PW length was additionally shortened and maybe results in premature truncated passwords. So the actually maximum length is 72/2 = 36 bytes (which is probably long enough for most practically used PW, but still bad)
  2. The salt was generated like this:
    saltBuilder.append(Bytes.wrap(HKDF.fromHmacSha256().expand(salt, "bcrypt".getBytes(), 16)).encodeHex());
    Due to the 'creative' way the jBcrypt API generates a salt, I implemented my own salt method to be able to pass a custom salt, but did it incorrectly. The salt SHOULD be 16 bytes encoded as Bcrypt Radix64 (= 22 bytes), but the 16 bytes where encoded to 32 characters hex. The jBcrypt impl then cuts 10 of those characters cutting 5 bytes of entropy making it a 11 byte hash

All this was discovered while trying to update the bcrypt impl with mine https://github.com/patrickfav/bcrypt.

Going forward:

  • I will replace the current Bcrypt stretcher with the new, correctly implemented one, that means that old encrypted preferences cannot be read anymore
  • The old bcrypt impl will still be in the code base, but deprecated, the data is still accessible
  • I will change the "change password" feature to also accept a new Keystrecht impl, so this issue can be migrated

Fixed by #17