微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么是最快的SHA1实施? OpenSSL SHA1: Boost :: SHA1: CryptoPP :: SHA1:

如何解决什么是最快的SHA1实施? OpenSSL SHA1: Boost :: SHA1: CryptoPP :: SHA1:

我正在寻找最快的SHA1实现,因为我必须对其进行数百万次的计算。我尝试了boost::uuids::detail::sha1OpenSSL SHA1,并且我发现OpenSSL的速度是boost的2.5倍。我还检查了Crypto++,它比其他两个要慢得多。这是我检查他们表现的方法

OpenSSL SHA1:

#include "openssl/sha.h"

void sha1_ossl (const unsigned char* data) {
    unsigned char  hash[20];
    for (long i=0; i<100000000; ++i) {
      SHA1(data,64,hash);
    
      if ((unsigned int)hash[0]==0 && (unsigned int)hash[1]==0 && (unsigned int)hash[2]==0 && (unsigned int)hash[3]==0)
          break;
    }
}

Boost :: SHA1:

#include <boost/uuid/detail/sha1.hpp>

void sha1_boost (const unsigned char* data) {
    boost::uuids::detail::sha1 sha1;
    unsigned hash[5];
    for (long i=0; i<100000000; ++i) {
        sha1.process_bytes(data,64);
        sha1.get_digest(hash);
        sha1.reset();
        if (hash[0]==0) break;
    }
}

CryptoPP :: SHA1:

#include <cryptopp/sha.h>
#include <cryptopp/hex.h>

void sha1_cryptoPP (const unsigned char* data) {
    std::string data_s (reinterpret_cast<char const*>(data));
    std::string hash_hex;
    CryptoPP::SHA1 sha1;
    for (long i=0; i<100000000; ++i) {
        CryptoPP::StringSource ss(data_s,true,new CryptoPP::HashFilter(sha1,new CryptoPP::HexEncoder(new CryptoPP::StringSink(hash_hex))));
        if (hash_hex.starts_with("00000000")) break;
    }
}

然后我用随机数据测试这些功能

int main() {
  const unsigned char data[65] = "tJQVfvcjGMNIvJfowXBjmSRcKtSjCcyQvaAdakfEJtgSNZHnOHCjkzGFwngiLFPm";
  sha1_boost (data);
  sha1_ossl (data);
  sha1_cryptoPP (data);
}

效果结果

我用g++ -O3 -std=c++2a编译了所有代码,以获得以下结果。我发现OpenSSL比其他实现更快,而Crypto ++最慢:

Performance of various SHA1 algorithms

问题

  • 最快的SHA1实现是什么?
  • 如何改善我的Crypto ++功能

感谢任何能改善性能的反馈。

解决方法

我的上一个实验证实,openssl的速度是其中几种最快的(包括Crypto ++以及一些我遗忘了哪些遗失的单源C实现)

Re:问题的代码审查类型部分:

  • 增强的“实现”来自细节名称空间,不应依赖。

  • 使用CryptoPP可能会受益于使用过程接口,而不是每次都动态地组成管道。具体来说,您不应转换为字符串来检查摘要的前n个字节。由于重复分配,这可能是运行时的主要部分。

    遵循程序界面,还可以使您使用reset / clear成员(从内存中引用)


    if ((unsigned int)hash[0] == 0 && (unsigned int)hash[1] == 0 &&
        (unsigned int)hash[2] == 0 && (unsigned int)hash[3] == 0)
        break;

应该很简单

    if (!(hash[0] || hash[1] || hash[2] || hash[3]))
        break;

甚至

    if (!std::any_of(hash+0,hash+4,std::identity{}))
        break;

改进的基准代码

结合了上述内容和更多内容(主要围绕良好的风格,避免指针错误,显示有效的迭代并允许dump检查摘要的准确性)

Live On Compiler Explorer

#include "openssl/sha.h"
#include <boost/uuid/detail/sha1.hpp>
#include <algorithm>
#include <iostream>
#include <iomanip>
using byte = unsigned char;

#ifndef ONLINE_DEMO
auto constexpr iterations = 100'000'000;
#else
auto constexpr iterations = 10000;
#endif

static void dump(byte const (&a)[20]) {
    for (unsigned b : a) {
        std::cout << std::setw(2) << std::setfill('0') << std::hex << b;
    }
    std::cout << std::dec << std::endl;
}

static void dump(uint32_t const (&a)[5]) {
    for (auto b : a) {
        std::cout << std::setw(8) << std::setfill('0') << std::hex << b;
    }
    std::cout << std::dec << std::endl;
}

long sha1_ossl(std::string_view data) {
    byte hash[20];
    for (long i = 0; i < iterations; ++i) {
        SHA1(reinterpret_cast<byte const*>(data.data()),data.size(),hash);

        //dump(hash);
        if (!std::any_of(hash+0,std::identity{}))
            return i;
    }
    return iterations;
}

long sha1_boost(std::string_view data) {
    boost::uuids::detail::sha1 sha1;
    uint32_t hash[5];
    for (long i = 0; i < iterations; ++i) {
        sha1.process_bytes(reinterpret_cast<byte const*>(data.data()),data.size());
        sha1.get_digest(hash);
        sha1.reset();
        //dump(hash);
        if (hash[0] == 0)
            return i;
    }
    return iterations;
}

#ifndef ONLINE_DEMO
#include <cryptopp/hex.h>
#include <cryptopp/sha.h>
long sha1_cryptoPP(std::string_view data) {
    byte digest[20];

    CryptoPP::SHA1 sha1;
    for (long i = 0; i < iterations; ++i) {
        sha1.Restart();
        sha1.Update(reinterpret_cast<byte const*>(data.data()),data.size());
        sha1.Final(digest);

        //dump(digest);
        if (!std::any_of(digest+0,digest+4,std::identity{}))
            return i;
    }
    return iterations;
}
#endif

#include <chrono>
using namespace std::chrono_literals;

int main() {
    static auto now = std::chrono::high_resolution_clock::now;
    constexpr static std::string_view data =
        "tJQVfvcjGMNIvJfowXBjmSRcKtSjCcyQvaAdakfEJtgSNZHnOHCjkzGFwngiLFPm";

    auto timed = [](auto caption,auto f) {
        auto const start = now();
        auto n = f(data);
        std::cout << caption << ": " << n << " in " << (now()-start)/1.0ms << "ms\n";
    };

    timed("sha1_boost",sha1_boost);
    timed("sha1_ossl",sha1_ossl);
#ifndef ONLINE_DEMO
    timed("sha1_cryptoPP",sha1_cryptoPP);
#endif
}

打印:

sha1_boost: 100000000 in 85660.5ms
sha1_ossl: 100000000 in 24652.6ms
sha1_cryptoPP: 100000000 in 34921.3ms

或在线(那里没有Crypto ++):

sha1_boost: 10000 in 8.71938ms
sha1_ossl: 10000 in 2.32025ms

这是一个很大的进步,但还是赢家。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?