Private encryption and signing keys should be encrypted #267

Open
opened 2013-06-27 14:39:54 +02:00 by DivineOmega · 6 comments
DivineOmega commented 2013-06-27 14:39:54 +02:00 (Migrated from github.com)

If we consider issue https://github.com/Bitmessage/PyBitmessage/issues/256 to be a prerequisite to this, we could encrypt the entire keys.dat file.

I see this working similar to the following:

Any save operations would save out encrypted using an (AES) encryption key generated from a user provided password combined with a random salt. The random salt would prefix the encrypted data. This would allow it be retrieved and used with the password for decryption.

  • When PyBitmessage starts up for the first time and the keys.dat does not exist, the user would be prompted for a password. After a password is entered, an encrypted keys.dat file would be created.
  • When PyBitmessage starts up and the keys.dat does exist, the user would be prompted for the password and the keys.dat would be decrypted in memory. This decrypted data would then fed and equivalent of the current shared.config object and be accessed as usual by the rest of the program.

Unfortunately, due to the fact decrypted must be attempted against every message received, we have to store the private keys decrypted in memory while the program remain running. I can't think of any way around this without the inconvenience of the user being prompted for the password every time a new message comes in.

I'd really like to hear everyone's thoughts, feedback and ideas. This is a reasonably big/complex change so it really needs to be got right.

If we consider issue https://github.com/Bitmessage/PyBitmessage/issues/256 to be a prerequisite to this, we could encrypt the entire keys.dat file. I see this working similar to the following: Any save operations would save out encrypted using an (AES) encryption key generated from a user provided password combined with a random salt. The random salt would prefix the encrypted data. This would allow it be retrieved and used with the password for decryption. - When PyBitmessage starts up for the first time and the keys.dat _does not_ exist, the user would be prompted for a password. After a password is entered, an encrypted keys.dat file would be created. - When PyBitmessage starts up and the keys.dat _does_ exist, the user would be prompted for the password and the keys.dat would be decrypted in memory. This decrypted data would then fed and equivalent of the current shared.config object and be accessed as usual by the rest of the program. Unfortunately, due to the fact decrypted must be attempted against every message received, we have to store the private keys decrypted in memory while the program remain running. I can't think of any way around this without the inconvenience of the user being prompted for the password every time a new message comes in. I'd really like to hear everyone's thoughts, feedback and ideas. This is a reasonably big/complex change so it really needs to be got right.
ghost commented 2013-06-27 15:20:19 +02:00 (Migrated from github.com)

Maybe it would be a better idea to use a standard container format for the keys? Like the one used to store ssh and ssl private keys.

Or maybe borrow the encrypted wallet implementation from the bitcoin armory client, I think its in python,

Maybe it would be a better idea to use a standard container format for the keys? Like the one used to store ssh and ssl private keys. Or maybe borrow the encrypted wallet implementation from the bitcoin armory client, I think its in python,
fiatflux commented 2013-06-27 15:34:52 +02:00 (Migrated from github.com)

AES is really fast. That's sometimes a good thing, but not necessarily so
here. Since we only need to decrypt a fairly small amount of data, slow is
acceptable and helps prevent bruteforce attacks. One way to mitigate is to
make key derivation slow. Suppose we generate the key through something
like bcrypt?

I'd also consider doing a cipher cascade along the lines of Schneier's:
concatenate(cipher1(OTP), cipher2(OTP^plaintext))

AES is really fast. That's sometimes a good thing, but not necessarily so here. Since we only need to decrypt a fairly small amount of data, slow is acceptable and helps prevent bruteforce attacks. One way to mitigate is to make key derivation slow. Suppose we generate the key through something like bcrypt? I'd also consider doing a cipher cascade along the lines of Schneier's: concatenate(cipher1(OTP), cipher2(OTP^plaintext))
jdguffey commented 2013-06-27 16:01:38 +02:00 (Migrated from github.com)

What about PKCS#8? It's supported by OpenSSL and the key(s) could be encrypted with PBKDF2 (From PKCS#5) without having to do anything except modifying OpenSSL lib calls (I believe).

What about PKCS#8? It's supported by OpenSSL and the key(s) could be encrypted with PBKDF2 (From PKCS#5) without having to do anything except modifying OpenSSL lib calls (I believe).
linkerlin commented 2013-06-28 10:04:44 +02:00 (Migrated from github.com)

PKCS#8 is a good choice.

PKCS#8 is a good choice.
Dokument commented 2013-07-01 19:09:38 +02:00 (Migrated from github.com)

I think as soon as they keys are encrypted by bitmessage, users will neglect safe practices. Even using encrypted containers is risky but at least it makes you think about it.

I think as soon as they keys are encrypted by bitmessage, users will neglect safe practices. Even using encrypted containers is risky but at least it makes you think about it.
acejam commented 2013-07-19 20:53:38 +02:00 (Migrated from github.com)

This sounds like a great idea.

This sounds like a great idea.
This repo is archived. You cannot comment on issues.
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Bitmessage/PyBitmessage-2025-02-19#267
No description provided.