Thank you, I just logged in to ask these exact questions.
I appreciate your candor on the unknoability of unknowns...AI has developed in ways that few of us predicted.
If I might, what exactly is the source of our entropy?
It ended up taking me more time than expected to formulate an answer, when accounting for transparency and the difference in pre/post 0.96.5 change in implementation and crypto library.
Common part shared across versionsEntropy at wallet generation is the mix of a PRNG pull from the crypto library and one of two sources of extra entropy.
- The crypto library pull always tracks down to an OS pull.
- The extra entropy source is either an explicit card deck shuffle when available (0.95+, card shuffle tab in wallet generation wizard), or extra sources of accumulated entropy.
* It consists of 3 parts:
1. list of timestamps for mouse and keyboard events since ArmoryQt start
2. set of sizes, timestamps and filenames of user system temp folder + possibly some system log file hashed content
3. screenshot of desktop
* The data is concatenated together and HMAC'd
* Ignores failure to gather data and/or empty pool, across any of the extra steps.
* While the position in code varies, the extra entropy code is the same across versions.
0.96.5 - Extra entropy request and generation:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/ui/Wizards.py#L166 *
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/ArmoryQt.py#L1078 - cryptolib pull:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/armoryengine/PyBtcWallet.py#L904 . Leads to, cpp side:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/EncryptionUtils.cpp#L75 . Which is Crypto++ fortuna implementation (X9.17, using AES). auto seeded, non blocking.
Fresh seed everytime since it's a local variable, and extra entropy forces a reseed too.
+ The typedef:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/EncryptionUtils.h#L118 + The constructor arguments + reseed (all defaults):
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/cryptopp/osrng.h#L101 . Crypto++ version copied into repo.
- Fortuna seed pulls BLOCKSIZE bytes from OS:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/cryptopp/osrng.cpp#L77 + Windows: the usual MicrosoftCryptoProvider + CryptGenRandom
+ Linux/OSX: reads from /dev/urandom
+ Failures are not silently on reseed pull or identical generation across AES blocks
- AES blocksize is 16 bytes, hardcoded here:
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/cryptopp/rijndael.h#L13 . All entropy sources are eventually hashed together (down to 32 bytes) then clamped to AES blocksize (down to 16 bytes)
- extra entropy notes -
. extra entropy is SHA256'd into a fresh fortuna seed (IncorporateEntropy leads to a reseed):
*
https://github.com/goatpig/BitcoinArmory/blob/v0.96.5/cppForSwig/EncryptionUtils.cpp#L840.97 - Extra entropy request and generation:
*
https://github.com/goatpig/BitcoinArmory/blob/dev/ui/Wizards.py#L298 *
https://github.com/goatpig/BitcoinArmory/blob/dev/ArmoryQt.py#L1055 - cryptolib pull -
. Python does not touch the root anymore, only provides the extra entropy.
*
https://github.com/goatpig/BitcoinArmory/blob/dev/armoryengine/PyBtcWallet.py#L484 . Pulls 32 bytes, cpp side:
*
https://github.com/goatpig/BitcoinArmory/blob/dev/cppForSwig/BridgeAPI/Wallets/Manager.cpp#L408 . Which goes over to libbtc:
*
https://github.com/libbtc/libbtc/blob/master/src/random.c#L86 + Windows: MicrosoftCryptoProvider + CryptGenRandom
+ Linux/OSX: reads from /dev/urandom or /dev/random depending on what's available on system at build time
+ Will not fail silently on bad pull
+ No fortuna or hashing, raw pull is returned
. libbtc built alongside on Armory on the same system. Revision hash: 07933995eb5010a016c75fb703a66023116013a3 (HEAD of master branch as of this writing)
- extra entropy notes -
. Linux: second entropy pull will not work on Wayland distros, needs addressed
. screenshot chokes (qt5/6 migration snafu)
. hashed then XOR'ed into the OS RNG pull:
*
https://github.com/goatpig/BitcoinArmory/blob/dev/cppForSwig/BridgeAPI/Wallets/Manager.cpp#L411Notes on OS sources - Microsoft's CryptoProvider: closed source, nuff said
- Linux/OSX: /dev/urandom can theoretically get exhausted. Unlikely, even more so for 32 bytes of data. Both implementation fail explicitly if they can't pull enough data.
Conclusion - This is a standard, run of the mill implementation for the OS pull, even the closed source Windows implementation. Should be enough on its own, but the Windows closed source pull is untrustworthy (typical).
- Implicit extra entropy is robust but can fail silently. Still decent amount of extra entropy across all OS variants.
- Explicit extra entropy is good if the user sticks to actually shuffling a deck of cards. Don't pick the cards manually if you're gonna use this, please. Poor value otherwise.
- Extra entropy is either hashed with or XOR'ed into OS pull, therefor it doesn't degrade OS pull quality.
- Amount up from 16 bytes to 32 bytes from 0.96.5 to 0.97. This is a paranoid nitpick really, EC over a 256 bits prime field offers roughly 128 bits worth of security.
- Note: should consider implementing the OS pull directly in the Armory code instead of letting the crypto lib do it, just for code readability.