目标是计算缓冲区的SHA1哈希值或多个缓冲区作为C ++程序的一部分。
答案 0 :(得分:6)
我不确定使用boost的UUID的人是否会正确地在哈希值中执行前导零(你的字符串应始终具有相同的长度),所以这里是一个简化版本的上面的例子可以做到这一点:
#include <cstdio>
#include <string>
#include <boost/uuid/sha1.hpp>
std::string get_sha1(const std::string& p_arg)
{
boost::uuids::detail::sha1 sha1;
sha1.process_bytes(p_arg.data(), p_arg.size());
unsigned hash[5] = {0};
sha1.get_digest(hash);
// Back to string
char buf[41] = {0};
for (int i = 0; i < 5; i++)
{
std::sprintf(buf + (i << 3), "%08x", hash[i]);
}
return std::string(buf);
}
答案 1 :(得分:0)
Boost提供SHA1哈希类作为Boost Uuid Library的一部分。虽然它是详细命名空间的一部分,意味着它是一种库私有的,它存在多年并且稳定。
计算文件SHA1哈希并将其打印到stdout的小例子:
前奏:
#include <boost/uuid/sha1.hpp>
#include <boost/detail/endian.hpp>
#include <boost/algorithm/hex.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <iostream>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
using namespace std;
主要功能:
int main(int argc, char **argv)
{
if (argc < 2) { cerr << "Call: " << *argv << " FILE\n"; return 1; }
const char *filename = argv[1];
int fd = open(filename, O_RDONLY);
if (fd == -1) { cerr << "open: " << strerror(errno) << ")\n"; return 1; }
vector<char> v(128*1024);
boost::uuids::detail::sha1 sha1;
for (;;) {
ssize_t n = read(fd, v.data(), v.size());
if (n == -1) {
if (errno == EINTR) continue;
cerr << "read error: " << strerror(errno) << '\n';
return 1;
}
if (!n) break;
sha1.process_bytes(v.data(), n);
}
static_assert(sizeof(unsigned) == 4, "we are assuming 4 bytes here");
unsigned hash[5] = {0};
sha1.get_digest(hash);
#ifdef BOOST_LITTLE_ENDIAN
for (unsigned i = 0; i < 5; ++i)
hash[i] = __builtin_bswap32(hash[i]); // GCC builtin
#endif
boost::algorithm::hex(boost::make_iterator_range(
reinterpret_cast<const char*>(hash),
reinterpret_cast<const char*>(hash+5)),
std::ostream_iterator<char>(cout)); cout << '\n';
int r = close(fd);
if (r == -1) { cerr << "close error: " << strerror(errno) << '\n';
return 1; }
return 0;
}
Boost的已使用部分不会在任何boost共享库上创建依赖项。由于Boost非常便携并且可用于各种架构,因此使用Boost计算SHA1哈希也非常便携。
答案 2 :(得分:0)
OpenSSL库是可移植的,高效的,在其他有用的功能中实现SHA1支持。可在大多数平台上使用......
答案 3 :(得分:0)
OpenSSL库包含一个用于不同散列方法的API,非常便于携带,并且可以在许多系统上使用。
使用推荐的EVP API OpenSSL来计算文件的SHA1哈希的C ++示例:
int main(int argc, char **argv)
{
try {
if (argc < 2) throw runtime_error(string("Call: ") + *argv
+ string(" FILE"));
const char *filename = argv[1];
int fd = open(filename, O_RDONLY);
if (fd == -1) throw runtime_error("Could not open " + string(filename)
+ " (" + string(strerror(errno)) + ")");
BOOST_SCOPE_EXIT(&fd) { close(fd); } BOOST_SCOPE_EXIT_END
const EVP_MD *md = EVP_sha1();
if (!md) throw logic_error("Couldn't get SHA1 md");
unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> md_ctx(EVP_MD_CTX_create(),
EVP_MD_CTX_destroy);
if (!md_ctx) throw logic_error("Couldn't create md context");
int r = EVP_DigestInit_ex(md_ctx.get(), md, 0);
if (!r) throw logic_error("Could not init digest");
vector<char> v(128*1024);
for (;;) {
ssize_t n = read(fd, v.data(), v.size());
if (n == -1) {
if (errno == EINTR)
continue;
throw runtime_error(string("read error: ") + strerror(errno));
}
if (!n)
break;
int r = EVP_DigestUpdate(md_ctx.get(), v.data(), n);
if (!r) throw logic_error("Digest update failed");
}
array<unsigned char, EVP_MAX_MD_SIZE> hash;
unsigned int n = 0;
r = EVP_DigestFinal_ex(md_ctx.get(), hash.data(), &n);
if (!r) throw logic_error("Could not finalize digest");
boost::algorithm::hex(boost::make_iterator_range(
reinterpret_cast<const char*>(hash.data()),
reinterpret_cast<const char*>(hash.data()+n)),
std::ostream_iterator<char>(cout));
cout << '\n';
} catch (const exception &e) {
cerr << "Error: " << e.what() << '\n';
return 1;
}
return 0;
}
示例的前奏:
#include <openssl/evp.h>
#include <boost/algorithm/hex.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/scope_exit.hpp>
#include <iostream>
#include <vector>
#include <array>
#include <memory>
#include <string>
#include <stdexcept>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
using namespace std;
对于EVP API,程序必须与libcrypto链接,例如:
g++ -g -std=c++11 sha1_example.cc -lcrypto
答案 4 :(得分:0)
Qt库从版本4.3开始包含支持各种哈希算法的类QCryptographicHash,包括SHA1。尽管Qt可以说比OpenSSL更不便携,但至少对于已经依赖于Qt QCryptographicHash的项目来说,这是计算SHA1哈希的明显方法。
计算文件SHA1哈希值的示例程序:
#include <QCryptographicHash>
#include <QByteArray>
#include <QFile>
#include <iostream>
#include <stdexcept>
using namespace std;
int main(int argc, char **argv)
{
try {
if (argc < 2)
throw runtime_error(string("Call: ") + *argv + string(" FILE"));
const char *filename = argv[1];
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Unbuffered))
throw runtime_error("Could not open: " + string(filename));
QCryptographicHash hash(QCryptographicHash::Sha1);
vector<char> v(128*1024);
for (;;) {
qint64 n = file.read(v.data(), v.size());
if (!n)
break;
if (n == -1)
throw runtime_error("Read error");
hash.addData(v.data(), n);
}
QByteArray h(hash.result().toHex());
cout << h.data() << '\n';
} catch (const exception &e) {
cerr << "Error: " << e.what() << '\n';
return 1;
}
return 0;
}
使用过的Qt类都是Qt核心库的一部分。一个示例cmake构建文件:
cmake_minimum_required(VERSION 2.8.11)
project(hash_qt CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
find_package(Qt5Core)
add_executable(hash_qt hash_qt.cc)
target_link_libraries(hash_qt Qt5::Core)
答案 5 :(得分:0)
Botan库实现了加密算法的“厨房接收器”,包括SHA1(当然)。它可以在提供最新C ++编译器的各种系统之间移植。
计算SHA1哈希值并将其作为十六进制字符串获取是直接使用Botan的高级流类C ++ API来构建管道。
计算文件SHA1哈希的示例:
#include <botan/pipe.h>
#include <botan/basefilt.h>
#include <botan/filters.h>
#include <botan/data_snk.h>
using namespace Botan;
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
try {
if (argc < 2)
throw runtime_error(string("Call: ") + *argv + string(" FILE"));
const char *filename = argv[1];
ifstream in(filename, ios::binary);
in.exceptions(ifstream::badbit);
Pipe pipe(new Chain(new Hash_Filter("SHA-1"),
new Hex_Encoder(Hex_Encoder::Lowercase)),
new DataSink_Stream(cout));
pipe.start_msg();
in >> pipe;
pipe.end_msg();
} catch (const exception &e) {
cerr << "Error: " << e.what() << '\n';
return 1;
}
return 0;
}
当哈希值应该作为字符串处理时,ostringstream
(而不是cout)可以用作数据宿流。
根据目标系统/发行版,可能会将头文件放置在稍微不寻常的位置,并且库可能包含稍微意外的后缀(例如在Fedora 21上)。以下是cmake代码段:
cmake_minimum_required(VERSION 2.8.11)
project(hash CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
find_library(LIB_BOTAN NAMES botan botan-1.10)
find_path(HEADER_BOTAN NAMES botan/pipe.h PATH_SUFFIXES botan-1.10)
add_executable(hash_botan hash_botan.cc)
set_property(TARGET hash_botan PROPERTY INCLUDE_DIRECTORIES ${HEADER_BOTAN})
target_link_libraries(hash_botan ${LIB_BOTAN})
答案 6 :(得分:0)
Crypto++库是一个可移植的C ++库,包含多种加密算法,包括SHA1等几种散列算法。
API提供了各种源和接收类,其中可以在其间附加一堆转换。
计算文件SHA1哈希的示例:
#include <cryptopp/files.h>
#include <cryptopp/filters.h>
#include <cryptopp/hex.h>
#include <cryptopp/sha.h>
using namespace CryptoPP;
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
try {
if (argc < 2)
throw runtime_error(string("Call: ") + *argv + string(" FILE"));
const char *filename = argv[1];
SHA1 sha1;
FileSource source(filename, true,
new HashFilter(sha1,
new HexEncoder(new FileSink(cout), false, 0, ""),
false)
);
} catch (const exception &e) {
cerr << "Error: " << e.what() << '\n';
return 1;
}
return 0;
}
可以通过例如:g++ -Wall -g -std=c++11 hash_cryptopp.cc -lcryptopp
Crypto ++'通过几个附加的转换将来自源的内容泵入接收器。而不是FileSink
其他接收器可用,例如StringSinkTemplate
用于直接写入字符串对象。
附加对象被引用计数,以便它们在范围出口处自动销毁。