Author

Topic: Testing Armory's encryption parameters, results and questions (Read 1439 times)

legendary
Activity: 3766
Merit: 1364
Armory Developer
Armory's KDF is a precursor of Scrypt. It is mostly memory bound, where the KDF keeps hashing pages upon pages of data that it has to keep in RAM because the final result requires data from unpredictable page indexes. What the user gets to control is the amount of RAM used for the most part. This makes stuff like GPU brute force attacks inefficient.
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
Bumping this because I also had this question and I found the answer to it.

1. What determines the target compute time?
(examples: number of AES rounds, key stretching derivations, etc.)

The target compute time is user set and 250 ms by default, Armory uses a KDF with SHA512, and a salt generated somewhere, to implement the intensity in the wallet encryption, and the KDF's parameters are calculated here. The compute time influences the number of iterations, and the amount of memory that it'll use, which is itself limited by the memory limit that you set (by default 32MB).

2. From my limited testing, it seems like raising the target compute time increases the required unlock memory. In fact, I went and did more doublings of target compute times, and it seems like for every doubling in compute time, the unlock memory doubles as well. What is the reasoning behind this?

Inside the KDF parameter calculation code I linked, there is a loop that looks for the optimal amount of KDF blocks (and hence memory) to use for the KDF. This is doubled each time in the loop, which roughly doubles the amount of time KDF takes:

Code:
  // Start the search for a memory value at 1kB
   memoryReqtBytes_ = 1024;
   double approxSec = 0;
   while(approxSec <= targetComputeSec/4 && memoryReqtBytes_ < maxMemReqts)
   {
      memoryReqtBytes_ *= 2;

      sequenceCount_ = memoryReqtBytes_ / hashOutputBytes_;
      lookupTable_.resize(memoryReqtBytes_);

      TIMER_RESTART("KDF_Mem_Search");
      testKey = DeriveKey_OneIter(testKey);
      TIMER_STOP("KDF_Mem_Search");
      approxSec = TIMER_READ_SEC("KDF_Mem_Search");
   }

Eventually there comes a breaking point where increasing the target compute time doesn't make the KDF take much longer because the memory limit in place will limit the amount of memory KDF can use, making the encryption process more memory-bound than time-bound.
full member
Activity: 209
Merit: 100
I'm playing around with Armory's wallet creation, and noticed two parameters that the user can determine: "Target compute time" and "Max memory usage". Question:

1. What determines the target compute time?
(examples: number of AES rounds, key stretching derivations, etc.)

To test the wallet's encryption properties, I created a few test cases with the following parameters and recorded the following results:

Target Compute Time   250 ms      
Max Memory Usage   32 MB      
            
Password Length   32   64   128
Time to Unlock   249 ms   246 ms   246 ms
Unlock Memory   4 MB   4 MB   4 MB


Target Compute Time   250 ms      
Max Memory Usage   64 MB      
            
Password Length   32   64   128
Time to Unlock   164 ms   255 ms   165 ms
Unlock Memory   4 MB   4 MB   4 MB


Target Compute Time   500 ms      
Max Memory Usage   32 MB      
            
Password Length   32   64   128
Time to Unlock   332 ms   334 ms   501 ms
Unlock Memory   8 MB   8 MB   8 MB


Target Compute Time   500 ms      
Max Memory Usage   64 MB      
            
Password Length   32   64   128
Time to Unlock   336 ms   501 ms   498 ms
Unlock Memory   8 MB   8 MB   8 MB

2. From my limited testing, it seems like raising the target compute time increases the required unlock memory. In fact, I went and did more doublings of target compute times, and it seems like for every doubling in compute time, the unlock memory doubles as well. What is the reasoning behind this?
Jump to: