26 #if CRYPTOPP_MSC_VERSION
27 # pragma warning(disable: 4355)
30 #if CRYPTOPP_MSC_VERSION
31 # pragma warning(disable: 4505 4355)
38 const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC;
39 #elif defined(CLK_TCK)
40 const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK;
42 const double CLOCK_TICKS_PER_SECOND = 1000000.0;
45 extern const byte defaultKey[] =
"0123456789"
46 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
47 "00000000000000000000000000000000000000000000000000000"
48 "00000000000000000000000000000000000000000000000000000";
50 double g_allocatedTime = 0.0, g_hertz = 0.0, g_logTotal = 0.0;
51 unsigned int g_logCount = 0;
52 time_t g_testBegin, g_testEnd;
54 inline std::string HertzToString(
double hertz)
56 std::ostringstream oss;
59 if (hertz >= 0.999e+9)
60 oss << hertz / 1e+9 <<
" GHz";
61 else if (hertz >= 0.999e+6)
62 oss << hertz / 1e+6 <<
" MHz";
63 else if (hertz >= 0.999e+3)
64 oss << hertz / 1e+3 <<
" KHz";
66 oss << hertz <<
" Hz";
71 void OutputResultBytes(
const char *name,
const char *provider,
double length,
double timeTaken)
73 std::ostringstream oss;
76 if (length < 0.000001f) length = 0.000001f;
77 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
79 double mbs = length / timeTaken / (1024*1024);
80 oss <<
"\n<TR><TD>" << name <<
"<TD>" << provider;
81 oss << std::setiosflags(std::ios::fixed);
82 oss <<
"<TD>" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << mbs;
85 const double cpb = timeTaken * g_hertz / length;
87 oss <<
"<TD>" << std::setprecision(2) << std::setiosflags(std::ios::fixed) << cpb;
89 oss <<
"<TD>" << std::setprecision(1) << std::setiosflags(std::ios::fixed) << cpb;
91 g_logTotal += log(mbs);
94 std::cout << oss.str();
97 void OutputResultKeying(
double iterations,
double timeTaken)
99 std::ostringstream oss;
102 if (iterations < 0.000001f) iterations = 0.000001f;
103 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
105 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*1000*timeTaken/iterations);
109 oss <<
"<TD>" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / iterations;
111 std::cout << oss.str();
114 void OutputResultOperations(
const char *name,
const char *provider,
const char *operation,
bool pc,
unsigned long iterations,
double timeTaken)
116 CRYPTOPP_UNUSED(provider);
117 std::ostringstream oss;
120 if (!iterations) iterations++;
121 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
123 oss <<
"\n<TR><TD>" << name <<
" " << operation << (pc ?
" with precomputation" :
"");
125 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations);
130 const double t = timeTaken * g_hertz / iterations / 1000000;
131 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << t;
134 g_logTotal += log(iterations/timeTaken);
137 std::cout << oss.str();
169 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
172 unsigned long i=0, blocks=1;
175 clock_t start = ::clock();
179 for (; i<blocks; i++)
181 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
183 while (timeTaken < 2.0/3*timeTotal);
186 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
191 const int BUF_SIZE=2048U;
193 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
196 unsigned long i=0, blocks=1;
199 clock_t start = ::clock();
203 for (; i<blocks; i++)
205 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
207 while (timeTaken < 2.0/3*timeTotal);
210 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
215 const int BUF_SIZE=2048U;
217 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
220 unsigned long i=0, blocks=1;
223 clock_t start = ::clock();
227 for (; i<blocks; i++)
228 bt.
Put(buf, BUF_SIZE);
229 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
231 while (timeTaken < 2.0/3*timeTotal);
234 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
239 const int BUF_SIZE = 2048U;
241 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
245 if (cipher != NULLPTR)
251 cipher->
SetKey(buf, size);
254 unsigned long long blocks = 1;
257 clock_t start = ::clock();
262 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
263 }
while (timeTaken < timeTotal);
266 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
273 void BenchMark(
const char *name,
NIST_DRBG &rng,
double timeTotal)
275 const int BUF_SIZE = 2048U;
277 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
281 unsigned long long blocks = 1;
284 clock_t start = ::clock();
289 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
290 }
while (timeTaken < timeTotal);
293 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
299 CRYPTOPP_UNUSED(params);
300 std::string name = factoryName;
305 BenchMark(name.c_str(), *obj, g_allocatedTime);
310 std::ostringstream oss;
313 oss <<
"<!DOCTYPE HTML>";
314 oss <<
"\n<HTML lang=\"en\">";
317 oss <<
"\n<META charset=\"UTF-8\">";
318 oss <<
"\n<TITLE>Speed Comparison of Popular Crypto Algorithms</TITLE>";
319 oss <<
"\n<STYLE>\n table {border-collapse: collapse;}";
320 oss <<
"\n table, th, td, tr {border: 1px solid black;}\n</STYLE>";
325 oss <<
"\n<H1><A href=\"http://www.cryptopp.com\">Crypto++</A> " << CRYPTOPP_VERSION / 100;
326 oss <<
'.' << (CRYPTOPP_VERSION % 100) / 10 <<
'.' << CRYPTOPP_VERSION % 10 <<
" Benchmarks</H1>";
328 oss <<
"\n<P>Here are speed benchmarks for some commonly used cryptographic algorithms.</P>";
331 oss <<
"\n<P>CPU frequency of the test platform is " << HertzToString(g_hertz) <<
".</P>";
333 oss <<
"\n<P>CPU frequency of the test platform was not provided.</P>" << std::endl;
335 std::cout << oss.str();
340 std::ostringstream oss;
341 oss <<
"\n</BODY>\n</HTML>\n";
342 std::cout << oss.str();
345 void BenchmarkWithCommand(
int argc,
const char*
const argv[])
347 std::string command(argv[1]);
348 float runningTime(argc >= 3 ? Test::StringToValue<float, true>(argv[2]) : 1.0f);
349 float cpuFreq(argc >= 4 ? Test::StringToValue<float, true>(argv[3])*
float(1e9) : 0.0f);
350 std::string algoName(argc >= 5 ? argv[4] :
"");
353 Benchmark(Test::All, runningTime, cpuFreq);
354 else if (command ==
"b3")
355 Test::Benchmark(Test::PublicKey, runningTime, cpuFreq);
356 else if (command ==
"b2")
357 Test::Benchmark(Test::SharedKey, runningTime, cpuFreq);
358 else if (command ==
"b1")
359 Test::Benchmark(Test::Unkeyed, runningTime, cpuFreq);
362 void Benchmark(Test::TestClass suites,
double t,
double hertz)
369 g_testBegin = ::time(NULLPTR);
371 if (
static_cast<int>(suites) == 0 ||
static_cast<int>(suites) > TestLast)
375 if (suites & Test::Unkeyed)
377 std::cout <<
"\n<BR>";
378 Benchmark1(t, hertz);
382 if (suites & Test::SharedKey)
384 std::cout <<
"\n<BR>";
385 Benchmark2(t, hertz);
389 if (suites & Test::PublicKey)
391 std::cout <<
"\n<BR>";
392 Benchmark3(t, hertz);
395 g_testEnd = ::time(NULLPTR);
397 std::ostringstream oss;
398 oss <<
"\n<P>Throughput Geometric Average: " << std::setiosflags(std::ios::fixed);
399 oss << std::exp(g_logTotal/(g_logCount > 0.0f ? g_logCount : 1.0f)) << std::endl;
401 oss <<
"\n<P>Test started at " << TimeToString(g_testBegin);
402 oss <<
"\n<BR>Test ended at " << TimeToString(g_testEnd);
404 std::cout << oss.str();
409 void Benchmark1(
double t,
double hertz)
416 cpb =
"<TH>Cycles/Byte";
420 std::cout <<
"\n<TABLE>";
422 std::cout <<
"\n<COLGROUP><COL style=\"text-align: left;\"><COL style=\"text-align: right;\">";
423 std::cout <<
"<COL style=\"text-align: right;\">";
424 std::cout <<
"\n<THEAD style=\"background: #F0F0F0\">";
425 std::cout <<
"\n<TR><TH>Algorithm<TH>Provider<TH>MiB/Second" << cpb;
427 std::cout <<
"\n<TBODY style=\"background: white;\">";
429 #ifdef NONBLOCKING_RNG_AVAILABLE
430 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"NonblockingRng");
432 #ifdef OS_RNG_AVAILABLE
433 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AutoSeededRandomPool");
434 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AutoSeededX917RNG(AES)");
436 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"MT19937");
437 #if (CRYPTOPP_BOOL_X86) && !defined(CRYPTOPP_DISABLE_ASM)
439 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"PadlockRNG");
441 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_ASM)
443 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"RDRAND");
445 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"RDSEED");
447 #if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) && !defined(CRYPTOPP_DISABLE_ASM)
449 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"DARN");
451 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AES/OFB RNG");
452 BenchMarkByNameKeyLess<NIST_DRBG>(
"Hash_DRBG(SHA1)");
453 BenchMarkByNameKeyLess<NIST_DRBG>(
"Hash_DRBG(SHA256)");
454 BenchMarkByNameKeyLess<NIST_DRBG>(
"HMAC_DRBG(SHA1)");
455 BenchMarkByNameKeyLess<NIST_DRBG>(
"HMAC_DRBG(SHA256)");
458 std::cout <<
"\n<TBODY style=\"background: yellow;\">";
460 BenchMarkByNameKeyLess<HashTransformation>(
"CRC32");
461 BenchMarkByNameKeyLess<HashTransformation>(
"CRC32C");
462 BenchMarkByNameKeyLess<HashTransformation>(
"Adler32");
463 BenchMarkByNameKeyLess<HashTransformation>(
"MD5");
464 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-1");
465 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-256");
466 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-512");
467 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-224");
468 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-256");
469 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-384");
470 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-512");
471 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-224");
472 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-256");
473 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-384");
474 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-512");
475 BenchMarkByNameKeyLess<HashTransformation>(
"Tiger");
476 BenchMarkByNameKeyLess<HashTransformation>(
"Whirlpool");
477 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-160");
478 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-320");
479 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-128");
480 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-256");
481 BenchMarkByNameKeyLess<HashTransformation>(
"SM3");
482 BenchMarkByNameKeyLess<HashTransformation>(
"BLAKE2s");
483 BenchMarkByNameKeyLess<HashTransformation>(
"BLAKE2b");
486 std::cout <<
"\n</TABLE>" << std::endl;
Classes for working with NameValuePairs.
Standard names for retrieving values by name when working with NameValuePairs.
virtual std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
SecBlock using AllocatorWithCleanup<byte, true> typedef.
Interface for NIST DRBGs from SP 800-90A.
virtual void IncorporateEntropy(const byte *input, size_t length)=0
Update RNG state with additional unpredictable values.
virtual void GenerateBlock(byte *output, size_t size)=0
Generate random array of bytes.
virtual unsigned int MinEntropyLength() const =0
Provides the minimum entropy size.
Interface for retrieving values given their names.
Interface for random number generators.
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
Sets or reset the key of this object.
bool IsResynchronizable() const
Determines if the object can be resynchronized.
virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms=g_nullNameValuePairs)
Sets or reset the key of this object.
virtual size_t DefaultKeyLength() const =0
Returns default key length.
Interface for one direction (encryption or decryption) of a stream cipher or cipher mode.
Pointer that overloads operator ->
Functions for CPU features and intrinsics.
bool HasPadlockRNG()
Determines Padlock RNG availability.
bool HasRDRAND()
Determines RDRAND availability.
bool HasDARN()
Determine if a PowerPC processor has DARN available.
bool HasRDSEED()
Determines RDSEED availability.
Abstract base classes that provide a uniform interface to this library.
const NameValuePairs & g_nullNameValuePairs
An empty set of name-value pairs.
Classes for NIST DRBGs from SP 800-90A.
Classes and functions for registering and locating library objects.
Class file for Mersenne Twister.
T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
Rounds a value up to a multiple of a second value.
Crypto++ library namespace.
Namespace containing testing and benchmark classes.
Classes for access to the operating system's random number generators.
Classes for VIA Padlock RNG.
Classes for RDRAND and RDSEED.
Classes for automatic resource management.