Skip to content

Instantly share code, notes, and snippets.

@aalness
Last active March 10, 2023 10:15
Show Gist options
  • Save aalness/577c7a6da1e669a07db9 to your computer and use it in GitHub Desktop.
Save aalness/577c7a6da1e669a07db9 to your computer and use it in GitHub Desktop.
Benchmark SHA256 for libsecp256k1 / crypto++ / openssl
#include <string.h>
#include <sys/time.h>
#include <iostream>
#include <openssl/sha.h>
#include <openssl/rand.h>
#include "secp256k1/src/hash_impl.h"
#include "cryptopp/sha.h"
static const size_t NUM_RUNS = 300000UL;
static double msecs(void)
{
struct timeval te;
gettimeofday(&te, NULL);
double msecs = te.tv_sec*1000.0 + te.tv_usec/1000.0;
return msecs;
}
static void openssl(const std::string& message, unsigned char* out)
{
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, message.c_str(), message.length());
SHA256_Final(out, &sha256);
}
static void cryptopp(const std::string& message, unsigned char* out)
{
CryptoPP::SHA256 hash;
hash.Update((const byte*)message.c_str(), message.length());
hash.Final(out);
}
static void secp256k1(const std::string& message, unsigned char* out)
{
secp256k1_sha256_t hasher;
secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)message.c_str(), message.length());
secp256k1_sha256_finalize(&hasher, out);
}
int main(int ac, char *av[])
{
if (ac != 2)
{
std::cout << "usage: " << av[0] << " <message size>" << std::endl;
return 1;
}
const size_t size = strtoul(av[1], 0, 0);
assert(size);
std::cout << "size: " << size << ", num runs: " << NUM_RUNS << std::endl;
// test correctness
for (size_t i = 0; i < 1000; ++i)
{
std::string message;
message.resize(size);
assert(RAND_bytes((unsigned char*)&message[0], size) == 1);
unsigned char out[32], out2[32], out3[32];
openssl(message, out);
cryptopp(message, out2);
secp256k1(message, out3);
assert(!memcmp(out, out2, 32));
assert(!memcmp(out, out3, 32));
}
std::string message;
message.resize(size);
assert(RAND_bytes((unsigned char*)&message[0], size) == 1);
double before, after;
before = msecs();
for (size_t i = 0; i < NUM_RUNS; ++i)
{
unsigned char out[32];
cryptopp(message, out);
}
after = msecs();
std::cout << " cryptopp took: " << (after-before) << "ms" << std::endl;
before = msecs();
for (size_t i = 0; i < NUM_RUNS; ++i)
{
unsigned char out[32];
openssl(message, out);
}
after = msecs();
std::cout << " openssl took: " << (after-before) << "ms" << std::endl;
before = msecs();
for (size_t i = 0; i < NUM_RUNS; ++i)
{
unsigned char out[32];
secp256k1(message, out);
}
after = msecs();
std::cout << "libsecp256k1 took: " << (after-before) << "ms" << std::endl;
return 0;
}
@aalness
Copy link
Author

aalness commented Dec 14, 2014

Yup. Had a similar thought but the numbers still work out the same. Code updated. I verified that at least with the cryptopp code it is using the ASM version of SHA256 transform.


andy@lab:~$ ./benchmark 32
size: 32, num runs: 300000
    cryptopp took: 286.192ms
     openssl took: 162.157ms
libsecp256k1 took: 352.647ms
andy@lab:~$ ./benchmark 256
size: 256, num runs: 300000
    cryptopp took: 900.827ms
     openssl took: 697.887ms
libsecp256k1 took: 1616.3ms
andy@lab:~$ ./benchmark 2048
size: 2048, num runs: 300000
    cryptopp took: 5015.51ms
     openssl took: 4536.79ms
libsecp256k1 took: 10477.9ms
andy@lab:~$ ./benchmark 8192
size: 8192, num runs: 300000
    cryptopp took: 19195ms
     openssl took: 17554.8ms
libsecp256k1 took: 40710.7ms

@aalness
Copy link
Author

aalness commented Dec 14, 2014

I don't think these #s are particularly damning or anything. For the normal workload of libsecp256k1 (on order of 32 bytes) it is perfectly fine. At least it would be remarkable if the difference mattered but we'd have much bigger problems to deal with in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment