0

I am using the library Crypto++ 5.6.5 and Visual Studio 2017.

How can I calculate the encryption time for AES-CCM?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Peace
  • 11
  • 1
    can't you just time the function call? – user3532232 Dec 23 '17 at 22:30
  • Would you please explain more in detail – Peace Dec 24 '17 at 10:34
  • Get and save the begin time, run the function, preferably in a loop for many iterations, get the end time, subtract the begin time and divide by the numner of iterations. Do this severaltimes and get the average. – zaph Dec 24 '17 at 17:50
  • 1
    generic duplicates about microbenchmarking in MSVC++: https://stackoverflow.com/questions/35725050/how-would-you-benchmark-the-performance-of-a-function, https://stackoverflow.com/questions/38250846/optimization-barrier-for-microbenchmarks-in-msvc-tell-the-optimizer-you-clobber, https://stackoverflow.com/questions/2349776/how-can-i-benchmark-c-code-easily, https://stackoverflow.com/questions/42603590/correct-way-of-portably-timing-code-using-c11. – Peter Cordes Dec 25 '17 at 20:45

1 Answers1

2

I would like to know how to calculate the encryption time for AES-CCM.

The Crypto++ wiki provides an article Benchmarks. It provides a lot of details regarding library performance, how throughput is calculated, and it even references the source code where the actual throughput is measured. Believe it or not, a simple call to clock works just fine to measure bulk encryption. Also see Benchmarks | Timing Loop in the same wiki article.

To benchmark AES/CCM, do something like the following. It is based on the Crypto++ benchmarking code, but it uses a ThreadUserTimer instead of a direct call to clock. ThreadUserTimer works across all OSes and all versions of C++.

You need to dial-in your processor speed at cpuFreq. You should also run ./governor.sh perf to move the CPU from an idle or C-level sleep state, but you can't because it is a Linux script. You can find it in the TestScript/ folder.

#include "cryptlib.h"
#include "secblock.h"
#include "hrtimer.h"
#include "osrng.h"
#include "modes.h"
#include "aes.h"
#include "ccm.h"
#include <iostream>

const double runTimeInSeconds = 3.0;
const double cpuFreq = 2.7*1000*1000*1000;

int main(int argc, char* argv[])
{
    using namespace CryptoPP;
    AutoSeededRandomPool prng;

    SecByteBlock key(16);
    prng.GenerateBlock(key, key.size());

    CCM<AES>::Encryption cipher;
    cipher.SetKeyWithIV(key, key.size(), key);

    const int BUF_SIZE=RoundUpToMultipleOf(2048U,
        dynamic_cast<StreamTransformation&>(cipher).OptimalBlockSize());

    AlignedSecByteBlock buf(BUF_SIZE);
    prng.GenerateBlock(buf, BUF_SIZE);

    double elapsedTimeInSeconds;
    unsigned long i=0, blocks=1;

    ThreadUserTimer timer;
    timer.StartTimer();

    do
    {
        blocks *= 2;
        for (; i<blocks; i++)
            cipher.ProcessString(buf, BUF_SIZE);
        elapsedTimeInSeconds = timer.ElapsedTimeAsDouble();
    }
    while (elapsedTimeInSeconds < runTimeInSeconds);

    const double bytes = static_cast<double>(BUF_SIZE) * blocks;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;
    const double mbs = bytes / 1024 / 1024 / elapsedTimeInSeconds;
    const double cpb = elapsedTimeInSeconds * cpuFreq / bytes;

    std::cout << cipher.AlgorithmName() << " benchmarks..." << std::endl;
    std::cout << "  " << ghz << " GHz cpu frequency" << std::endl;
    std::cout << "  " << cpb << " cycles per byte (cpb)" << std::endl;
    std::cout << "  " << mbs << " MiB per second (MiB)" << std::endl;
    // std::cout << "  " << elapsedTimeInSeconds << " seconds passed" << std::endl;
    // std::cout << "  " << (word64) bytes << " bytes processed"  << std::endl;

    return 0;
}

Running it on a Core i5-6400 at 2.7 GHz results in:

$ g++ bench.cxx ./libcryptopp.a -o bench.exe
$ ./bench.exe
AES/CCM benchmarks...
  2.7 GHz cpu frequency
  3.00491 cycles per byte (cpb)
  856.904 MiB per second (MiB)

Usually you benchmark a library with CTR mode. For example, all of the SUPERCOP benchmarks are performed using the mode. You can switch to CTR mode by including "modes.h", and then:

CTR_Mode<AES>::Encryption cipher;
cipher.SetKeyWithIV(key, key.size(), key);

Finally, the same test using CTR mode:

$ ./bench.exe
AES/CTR benchmarks...
  2.7 GHz cpu frequency
  0.568922 cycles per byte (cpb)
  4525.97 MiB per second (MiB)
jww
  • 97,681
  • 90
  • 411
  • 885
  • Are the duplicates I used to close this too generic? Should this be reopened, or edit the dup-list to more specific duplicates? I wasn't expecting there to be a good answer to a question that looked so generic, but now that you wrote one the question is maybe worth polishing. – Peter Cordes Dec 25 '17 at 20:33
  • @PeterCordes - Good question. Originally I was going to ping you and ask you to reconsider the close. When I read the question I saw there were two parts. First was the basic "benchmark" part that has been asked and answered many times. Second is the Crypto++ part. This answer focuses on the Crypto++ part, like using the `BlockTransformation` class' `ProcessString` to process a block and using Crypto++ `ThreadUserTimer` to get a timer that works well on all OSes and all versions of C++. `ThreadUserTimer` is not perfect, but there's a lot to be said about OS and C++ portability. – jww Dec 25 '17 at 20:40
  • I'm pretty aggressive closing questions as duplicates because I know it can be reversed if it turns out to be a mistake. People should definitely ping me if they don't think I did the right thing, and/or vote to reopen. – Peter Cordes Dec 25 '17 at 20:47