Jump to content
apollo13

Enpass 6 encryption details

Recommended Posts

Hi,

I am currently testing enpass 6 and parts of my tests included reading the actual encrypted SQLite database. I wasn't able to decrypt the files using the sqlcipher program:

sqlcipher vault.enpassdb 
SQLCipher version 3.15.2 2016-11-28 19:13:37
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> PRAGMA key='test123456';
sqlite> PRAGMA kdf_iter=100000;
sqlite> SELECT count(*) FROM sqlite_master;
Error: file is encrypted or is not a database

I have taken kdf_iter  from the vault.json file next to the actual vault file. What am I missing? Are you no longer using SQLCipher?

Thanks,
Florian

Edited by apollo13

Share this post


Link to post
Share on other sites

Hi @apollo13,

Thanks for writing in.

Enpass 6 derives a key from the master password with PBKDF2-HMAC-SHA512 100K iterations (outside of SQLCipher) and uses it as the raw key for SQLCipher. Salt is  first 16 byte of Sqlcipher database file. You need to follow the same procedure.

Thanks!

Share this post


Link to post
Share on other sites

Hi @Anshu kumar,
I've tried generating the key in python:

In [9]: hashlib.pbkdf2_hmac('sha256', b'test123456', b'', 100000).hex()
Out[9]: '88a4dbc9afab5c7fc7875a84b1a137478d9f7a74b4b0881d40bfaa5ecfb81c93'

and then in sqlcipher:

sqlite> PRAGMA key="x'88a4dbc9afab5c7fc7875a84b1a137478d9f7a74b4b0881d40bfaa5ecfb81c93'";
sqlite> SELECT count(*) FROM sqlite_master;
Error: file is encrypted or is not a database

what are you using as salt?

Edited by apollo13

Share this post


Link to post
Share on other sites

Hi @Anshu kumar,

I've used

hashlib.pbkdf2_hmac('sha256', b'test123456', open('vault.enpassdb', 'rb').read(16), 100000).hex()

now to generate the new key; I still get

Error: file is encrypted or is not a database

How is the password set? UTF-8 encoded bytes of the actual master password?

Share this post


Link to post
Share on other sites

Hi @Vinod Kumar,
good catch, that was my mistake. The final command:

hashlib.pbkdf2_hmac('sha512', b'test123456', open('vault.enpassdb', 'rb').read(16), 100000).hex()[:64]

So basically what Enpass uses as key:

  • pbkdf2_hmac_sha512 with (currently) 100k iterations (see vault.json for the current count)
  • the first 16 byte of the encrypted file as sault
  • the result of the keyderivation is hex encoded and limited to 64 hex digits

Thanks,
Florian

Edited by apollo13

Share this post


Link to post
Share on other sites

Wow, thanks for being so forthcoming with these information.

That really shows that you take security seriously (because obscurity won't work).

Enpass rocks!

Share this post


Link to post
Share on other sites
18 hours ago, apollo13 said:

Hi @Vinod Kumar,
good catch, that was my mistake. The final command:


hashlib.pbkdf2_hmac('sha256', b'test123456', open('vault.enpassdb', 'rb').read(16), 100000).hex()[:64]

So basically what Enpass uses as key:

  • pbkdf2_hmac_sha512 with (currently) 100k iterations (see vault.json for the current count)
  • the first 16 byte of the encrypted file as sault
  • the result of the keyderivation is hex encoded and limited to 64 bytes

Thanks,
Florian

In your call you still select sha256 instead of sha512 as hashing algorithm.

Secondly, when converting to hex you get 64 digits (not bytes!) for SHA256 and 128 for SHA512.
256 bits = 64 hex digits = 32 bytes.
512 bits = 128 hex digits = 64 bytes.

I would assume that there is an error in the algorithm. Because using SHA512 and then limiting the result to 64 hex digits seems counter productive. You basically throw away half of your hash for no reason and reduce the encryption key size by half. Not sure if that is intended. Even though a 32 byte symmetric encryption key is already hard to crack, except for the fact that the entropy is limited due to the available alphabet being 0-9 and a-f. So if I remember my lectures correctly that would make 1632 (=24^32=24*32=2128) different combinations instead of 2256.

Share this post


Link to post
Share on other sites

Hi @totkeks,
yes, that was a copy & paste error in the forum. I've fixed my command in the previous post. I am not sure what to tell you but SQLCipher docs say:
 

Quote

Alternatively, it is possible to specify an exact byte sequence using a blob literal. With this method, it is the calling application's responsibility to ensure that the data provided is a 64 character hex string, which will be converted directly to 32 bytes (256 bits) of key data.

Given that the sha512 hash is longer I just truncated -- I just tried to open the file; not exactly sure what enpass actually wants to do :)

EDIT:// I've verified that the full 64 bytes / 128 hex digits from my hashing do not open the sql database; you need to pass the truncated value.

Also I am not sure that:

1 hour ago, totkeks said:

Even though a 32 byte symmetric encryption key is already hard to crack, except for the fact that the entropy is limited due to the available alphabet being 0-9 and a-f.

holds, the SQLCipher docs say that they are converting the hex string back to bytes and using that as key instead of the hex string as bytes directly.

Edited by apollo13

Share this post


Link to post
Share on other sites
6 hours ago, apollo13 said:

Given that the sha512 hash is longer I just truncated -- I just tried to open the file; not exactly sure what enpass actually wants to do

Ah okay, then they just use SHA512 for harder to break hashes or something.

6 hours ago, apollo13 said:

the SQLCipher docs say that they are converting the hex string back to bytes and using that as key instead of the hex string as bytes directly.

Thanks for the hint, then my doubts were for no reason.

I guess we should sticky the algorithm description and the python example somewhere.

Share this post


Link to post
Share on other sites
12 minutes ago, totkeks said:

I guess we should sticky the algorithm description and the python example somewhere.

Yeah, some FAQ or https://www.enpass.io/security would probably be a good place. Didn't get a time to look into the data inside the database, but I think the individual values might also be encrypted. That information should then get added too.

Share this post


Link to post
Share on other sites

Dear Enpass Team,

Could you please share some more detailed info on how to decrypt the AES keys inside the DB? The notes in the security whitepaper are rather brief and a bit too concise. There seem to be multiple tables (Identity, vault_info, etc) that contain binary data and it's unclear how to extract the AES key and initialization vector.

Thanks.

Share this post


Link to post
Share on other sites

@Anshu kumar I would like to support the request for more information. While we know how to read the encrypted database at all, there is no proper information how the passwords are encrypted in the database (how to decrypt the "key" field in items, how to access additional vaults, etc.). The security whitepaper does not explain this. Without this information it is impossible to properly check the security of Enpass and come to a judgement. You were above lauded for not trying "security by obscurity" but one might differ considering this.

So please give us more information. This would really be appreciated. Thank you!

Edited by juja

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...