Add wallet privkey encryption. #232

pull TheBlueMatt wants to merge 2 commits into bitcoin:master from TheBlueMatt:encprivkeys changing 20 files +1394 −71
  1. TheBlueMatt commented at 11:27 PM on May 17, 2011: member

    This commit adds support for ekeys, or encrypted private keys, to the wallet. All keys are stored in memory in their encrypted form and thus the passphrase is required from the user to spend coins, or to create new addresses.

    Keys are encrypted with AES-256-CBC through OpenSSL's EVP library. The key is calculated via EVP_BytesToKey using AES256 with 1000 rounds.

    Each RPC command which requires the password in practice has an additional parameter, namely that password. Due to the need to convert the types of other parameters before sending them, users who do not use encryption (via the -nocrypt option) will have to specify a blank string (or any string) as the first parameter, followed by the command they currently use.

    Whenever keying material (unencrypted private keys, the user's password, the wallet's AES key) is stored unencrypted in memory, any reasonable attempt is made to mlock/VirtualLock that memory before storing the keying material. This is not true in several (commented) cases where mlock/VirtualLocking the memory is not possible.

    Although encryption of private keys in memory can be very useful on desktop systems (as some small amount of protection against stupid viruses), on an RPC server, the password is entered fairly insecurely. Thus, the only main advantage encryption has for RPC servers is for RPC servers that do not spend coins, except in rare cases, eg. a webserver of a merchant which only receives payment except for cases of manual intervention.

    Thanks to jgarzik for the original patch and sipa for all his input.

  2. TheBlueMatt commented at 11:34 PM on May 17, 2011: member
  3. Add wallet privkey encryption.
    This commit adds support for ekeys, or encrypted private keys, to the wallet.
    All keys are stored in memory in their encrypted form and thus the passphrase
    is required from the user to spend coins, or to create new addresses.
    
    Keys are encrypted with AES-256-CBC through OpenSSL's EVP library. The key is
    calculated via EVP_BytesToKey using AES256 with 1000 rounds.
    
    When the user is attempting to call RPC functions which require the password
    to unlock the wallet, an error will be returned unless they call
    walletpassword <password> <time to keep key in memory> first.
    
    A topupkeypool command has been added which tops up the users keypool
    (requiring the password via walletpassword first).
    keypoolsize has been added to the output of getinfo to show the user the
    number of keys left before they need to specify their password and call
    topupkeypool.
    
    A walletpasswordchange <oldpassword> <newpassword> has been added to allow
    the user to change their password via RPC.
    
    Whenever keying material (unencrypted private keys, the user's password, the
    wallet's AES key) is stored unencrypted in memory, any reasonable attempt is
    made to mlock/VirtualLock that memory before storing the keying material.
    This is not true in several (commented) cases where mlock/VirtualLocking the
    memory is not possible.
    
    Although encryption of private keys in memory can be very useful on desktop
    systems (as some small amount of protection against stupid viruses), on an
    RPC server, the password is entered fairly insecurely. Thus, the only main
    advantage encryption has for RPC servers is for RPC servers that do not spend
    coins, except in rare cases, eg. a webserver of a merchant which only receives
    payment except for cases of manual intervention.
    
    Thanks to jgarzik for the original patch and sipa for all his input.
    4b82ff1113
  4. Fix constant address return. 362006c53e
  5. gstarnberger commented at 5:34 AM on June 14, 2011: none

    Instead of using EVP_BytesToKey for key derivation I think scrypt (https://www.tarsnap.com/scrypt.html) should provide a somewhat better security against brute-force attacks.

  6. TheBlueMatt commented at 10:04 AM on June 14, 2011: member

    @sysfrog Im not sure. Though it may claim to be more secure, 1000 rounds on OpenSSL's algorithm is also very secure and I think I'd rather use a more common/well used/well analysed algorithm like OpenSSL's entire code base is.

  7. TheBlueMatt commented at 10:05 AM on June 14, 2011: member

    @dizzyd Ill take a look at updating to your other recommendations when I have a chance.

  8. dizzyd commented at 1:49 PM on June 14, 2011: none

    re: the unused IV -- "may be some kind of crazy issue.." is not a logical argument. Being paranoid about security is good, but there needs to be some basis in reality for it. Otherwise, you wind up with a lot of code that doesn't do anything and may obscure what's really going on.

    re: calls to SetKey mlocking -- if that's the case, then you really don't need to copy it to vchKey. All that serves to do is increase the number of copies of keys you have in memory and increases your attack surface.

    Security-wise: careful, minimal code > paranoid code. B0.02 from a random coder. :)

  9. witkamp commented at 6:07 PM on June 14, 2011: none

    Is there a reason you are not using a random salt?

  10. enmaku commented at 4:50 PM on June 16, 2011: contributor

    witkamp:

    Is there a reason you are not using a random salt?

    Yeah, password data should be salted - I mean we DO already have a giant network of people with high-end GPUs and the drivers/software necessary to brute force such things ;)

  11. gstarnberger commented at 5:13 PM on June 16, 2011: none

    @TheBlueMatt As far as I understand scrypt the main advantage over older techniques is that it not only adds computational complexity to calculate a given key from a password, but that each calculation also requires a given amount of RAM. So it's much harder to parallelize an attack with, e.g., an ASIC, as you would need lots of RAM to do so.

    But I agree with you: There have been much more reviews of the SSL code base, and so the chance of critical errors in OpenSSL is much lower compared to scrypt.

  12. TheBlueMatt commented at 5:24 PM on June 16, 2011: member

    @witkamp mostly because it would be a pain to store. This patch already uses the public key as the IV for the encryption of each private key so any kind of brute force/dictionary attack is already ridiculously difficult, I dont see a major advantage to adding a random salt to be used for a given wallet (and then stored in the wallet) as to brute force a wallet, you already need to know some of the information in the wallet (namely the public keys). But maybe others disagree? @sysfrog OK, so its agreed then that OpenSSL key derivation is probably the best way to go? @dizzyd Still planning on updating with some of your original recommendations, but I'm on vacation atm and dont feel like doing much coding.

  13. enmaku commented at 5:30 PM on June 16, 2011: contributor

    @TheBlueMatt gotcha, didn't see the public key = IV bit but it makes sense and stops dictionary/BF attacks at least as well as a random salt so I'm happy with it as a solution.

  14. dizzyd commented at 7:49 PM on June 16, 2011: none

    On Thu, Jun 16, 2011 at 11:24 AM, TheBlueMatt < reply@reply.github.com>wrote:

    @dizzyd Still planning on updating with some of your original recommendations, but I'm on vacation atm and dont feel like doing much coding.

    No worries -- I read your last reply first and was confused. :)

    D.

  15. phantomcircuit commented at 2:17 AM on June 19, 2011: none

    It would be best to use AES128 and not AES256. The key schedule in AES256 is known to be weak.

    http://www.schneier.com/blog/archives/2009/07/another_new_aes.html

  16. jrmithdobbs commented at 6:08 AM on June 20, 2011: contributor

    Please salt that passphrase properly as suggested in gmaxwell's forum post.

  17. mutantmonkey commented at 2:09 AM on June 21, 2011: none

    @phantomcircuit That attack is effective against 11-round AES-256, but not full 14-round AES-256. It'd be better to increase the number of rounds (he recommends 28 or more in that article) used instead of using a smaller key size. There are plenty of attacks on AES-128 as well, many of which were published after that article was written.

  18. TheBlueMatt commented at 10:20 PM on June 26, 2011: member

    Closing this in anticipation of the new branch.

  19. TheBlueMatt closed this on Jun 26, 2011

  20. dexX7 referenced this in commit c303de6dea on Dec 11, 2014
  21. sipa referenced this in commit a591d98c32 on Apr 22, 2015
  22. dexX7 referenced this in commit a8836d0f1b on Sep 18, 2015
  23. TheBlueMatt referenced this in commit 582b2934e6 on Oct 20, 2015
  24. deadalnix referenced this in commit d5b53aa818 on Jan 19, 2017
  25. lateminer referenced this in commit 90dbee19c9 on Dec 9, 2017
  26. attilaaf referenced this in commit 44c57eb8ce on Jan 13, 2020
  27. Losangelosgenetics referenced this in commit 9d0b592d4d on Mar 12, 2020
  28. cryptapus referenced this in commit 2bbd42bc2e on May 3, 2021
  29. hebasto referenced this in commit e614cc8cd8 on Aug 11, 2021
  30. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 21:16 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me