[C ++ openssl SHA256运行速度比JDK SHA256实现慢

问题描述 投票:0回答:1

我正在从事一个项目,作为项目的一部分,我必须大致模拟比特币工作量证明的计算。这涉及在固定的“ BlockHash”字符串和一个32位int随机数的串联上迭代计算SHA256两次,每次迭代均递增。如果计算的哈希值小于“ TargetHash”字符串,我们将中断循环并打印现时值。

我正在尝试比较两个顺序的实现,一个使用OpenSSL的SHA256实现使用C ++编写,另一个使用JDK的内部SHA256实现使用Java编写。我原以为OpenSSL的实现要比JDK快得多,但正相反。

这是我的Java代码:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class SHA256 {
    /**
     * convert byte[] to hex string
     *
     * @param hash
     * @return hex string
     */
    private static String bytesToHex(byte[] hash) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < hash.length; i++) {
            String hex = Integer.toHexString(0xff & hash[i]);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * get a sha256 of the input string
     *
     * @param inputString
     * @return resulting hash in hex string
     */
    public static String SHA256(String inputString) {
        try {
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            return bytesToHex(sha256.digest(inputString.getBytes(StandardCharsets.UTF_8)));
        } catch (NoSuchAlgorithmException ex) {
            System.err.println(ex.toString());
            return null;
        }
    }

    public static void main(String[] args){
        String blockHash = SHA256("Some random string to generate a block hash.");
        System.out.println("blockHash: " + blockHash);
        String targetHash = "000000938023b712892a41e8438e3ff2242a68747105de0395826f60b38d88dc";
        String tmp_hash="undefined";
        int nonce = 0;
        for(nonce=Integer.MIN_VALUE; nonce<=Integer.MAX_VALUE; nonce++) {
            tmp_hash = SHA256(SHA256(blockHash+String.valueOf(nonce)));
            if(targetHash.compareTo(tmp_hash)>0)
                break;
        }
        System.out.println("Resulting Hash: " + tmp_hash);
        System.out.println("Nonce:" + nonce);
    }
}

这是我的C ++实现:

#include <iostream>
#include <climits>
#include <cstring>
#include <sstream>
#include <string>
#include <iomanip>
#include "format.h"

using namespace std;

#include <openssl/sha.h>

string sha256(const string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    stringstream ss;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        ss << hex << setw(2) << setfill('0') << (int)hash[i];
    }
    return ss.str();
}


int main(int argc, char *argv[])
{   
    string input = "Some random string to generate a block hash.";
    string blockHash = sha256(input);
    cout << "blockHash: " << blockHash << endl;
    string targetHash = "000000938023b712892a41e8438e3ff2242a68747105de0395826f60b38d88dc";
    string tmp_hash="undefined";
    int nonce = 0;

    for(nonce = INT_MIN; nonce <= INT_MAX; nonce++){
        tmp_hash = sha256(sha256(fmt::format("{}{}", blockHash, nonce)));
        if(strcmp(tmp_hash.c_str(), targetHash.c_str()) < 0)
            break;
    }

    cout<<"Resulting Hash: "<<tmp_hash<<endl;
    cout<<"Nonce: "<<nonce<<endl;

    return 0;
}

使用linux'time'实用程序来测量运行时的输出:

javac SHA256.java
time java SHA256
blockHash: 596143a6a70a23c86e4b218afeb05d151ed45a39e96368e213d17e0a491d894a
Resulting Hash: 0000008ce61c628ffb00b6668687504fd5d44da0a57adb40d6ff59f8e4af0a4a
Nonce:-2135751361

real    0m22.258s
user    0m22.977s
sys 0m0.097s

g++ -O2 -DFMT_HEADER_ONLY main.cpp -lcrypto -lssl
time ./a.out
blockHash: 596143a6a70a23c86e4b218afeb05d151ed45a39e96368e213d17e0a491d894a
Resulting Hash: 0000008ce61c628ffb00b6668687504fd5d44da0a57adb40d6ff59f8e4af0a4a
Nonce: -2135751361

real    0m35.703s
user    0m35.693s
sys 0m0.005s

这只是用于简单的TargetHash,对于更困难的TargetHash,差异更大。我很确定,这里的openssl sha256实现不是瓶颈,还有其他问题,但是对于C ++来说,我不确定是什么。我之前使用过to_string(nonce)和s1.compare(s2),我将它们替换为fmt :: format和strcmp,因为它们速度更快,但仍然只能获得几秒钟的时间。任何想法将不胜感激。

java c++ openssl bitcoin sha256
1个回答
-1
投票

您的C ++代码的瓶颈是您的自定义bytes_to_string函数。循环调用stringstream函数只会降低性能。

您可能想在另一个问题上查看此answer

© www.soinside.com 2019 - 2024. All rights reserved.