2012 Update: It's now been a few months since this event, so I think it's safe to describe, for the record, what actually happened. The Bitcoin wallet file is managed by BSDDB, which is a database engine. Presumably, a database engine was used, in order to ensure ACID transactions (
atomicity,
consistency,
isolation,
durability), which makes sure that the database won't be corrupted by inconveniently-timed power outtages, etc. Most importantly, it should protect your private keys from ever getting corrupted.
The problem with a database manager, though, is that it does its own thing with the file storage. It's a
black box in terms of its behavior when you tell it to "delete" something. You'd hope it would actually remove the data, or at least blank it out, but that's not necessarily true. In the case of BSDDB, when Satoshi client says "delete this key and replace it with the encrypted key" it seems to not actually do that. Instead, it simply
marks the entry deleted, and then appends the new data to the end of the file. It doesn't even overwrite the original data.
From the user perspective, this is completely transparent, because the user must ask the BSDDB interface for the data, and BSDDB reports that it's gone, since the pointer to the data was discarded.
But, it's still in the binary file!
Before wallet encryption, I had written a pure-binary key-extractor script, to pull my private keys out of the wallet file (it was an elaborate search using the ECDSA library to find public-keys and find the associated private-key nearby). After Bitcoin 0.4.0 was released with wallet encryption, I re-ran my script for fun. To my surprise, it found 36 of 112 private keys! Whoops!
I wasn't too involved in the fix for the problem, since I have no experience with BSDDB. But the solution had to do with convincing the database to
actually remove/overwrite the data, and allow for wallets to be "born" encrypted to avoid any risk of it happening again. I don't know the gory details though, you'd have to ask the devs for specific details about how they fixed it.
Original Post: I think I might've found a bug in the wallet encryption.
Edit:
This problem has been fixed in the client version 0.5.0. Please see the
release notes for information on fixing your wallet. The most important information is:
If you have a previously encrypted wallet.dat, the first time you run bitcoin-qt or bitcoind the wallet will be rewritten, Bitcoin will shut down, and you will be prompted to restart it to run with the new, properly encrypted file.
If you had a previously encrypted wallet.dat that might have been copied or stolen (for example, you backed it up to a public location) you should send all of your bitcoins to yourself using a new bitcoin address and stop using any previously generated addresses.