从 boost::compute::detail::sha1 生成 boost::uuids::uuid
Generate boost::uuids::uuid from boost::compute::detail::sha1
我正在尝试以这种方式生成 boost::uuids::uuid from boost::compute::detail::sha1:
#include <iostream>
#include "boost/uuid/uuid.hpp"
#include "boost/uuid/uuid_io.hpp"
#include "boost/uuid/string_generator.hpp"
#include "boost/compute/detail/sha1.hpp"
int main(int argc, char* argv[])
{
try
{
boost::compute::detail::sha1 sha1("b888e35f9edf3794760392e1066d69-f43d-452e-8475-a09bae9a2e8500000000-0000-0000-0000-000000000000");
std::string str = sha1;
boost::uuids::uuid uuid = boost::uuids::string_generator()(str); // ERROR HERE!!
}
catch (std::exception& e)
{
std::cerr << "Error occurred: " << e.what() << std::endl;
}
return 0;
}
但是此代码失败并出现错误 Error occurred: invalid uuid string
(见上文)
我正在使用 Visual Studio 2017,Boost 1.67
我的错误在哪里?如何从 boost::compute::detail::sha1
生成 boost::uuids::uuid
PS:该代码适用于以前的增强版本。
从任意字符串的 SHA1 散列中获取 UUID 的正确、受支持的方法如下:
#include <string_view>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/name_generator_sha1.hpp>
boost::uuids::uuid uuid_from_string(std::string_view const input) {
static constexpr boost::uuids::uuid ns_id{}; // †null root, change as necessary
return boost::uuids::name_generator_sha1{ns_id}(input.data(), input.size());
}
(std::string_view
用于说明;如果这对您来说不理想,请使用 std::string
或 char const*
或任何合适的内容。)
虽然这是正确的方法,但有两个重要注意事项:
根据 RFC 4122,您需要为您的 UUID 提供命名空间;基本上这是你的 SHA1 散列的盐。 DNS 名称、URL、ISO OID 和 X.500 专有名称都有预定义的名称空间,但由于您的输入似乎与您需要定义的任何名称都不匹配;如标有 † 的行所示,此处使用 null 名称空间进行说明。可以在这个 SO 答案中找到 UUID 名称空间的更详细解释:Generating v5 UUID. What is name and namespace?
此代码的输出与您问题中代码的输出完全不同; iff 您需要输出与旧代码匹配您可以执行以下操作:
#include <cstring>
#include <string_view>
#include <boost/endian/conversion.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/detail/sha1.hpp>
boost::uuids::uuid uuid_from_string_old(std::string_view const input) {
boost::uuids::detail::sha1::digest_type digest;
{
boost::uuids::detail::sha1 h;
h.process_bytes(input.data(), input.size());
h.get_digest(digest);
}
boost::uuids::uuid ret;
auto p = ret.begin();
for (std::size_t i{}; i != 4; p += 4, ++i) {
auto const d = boost::endian::native_to_big(digest[i]);
std::memcpy(p, &d, 4);
}
return ret;
}
这会产生相同的输出,从 this demo 可以看出,使用带有 Boost 1.65.1 的旧代码。这违背了我从未直接使用别人的 detail
命名空间的评论政策,但除非你能找到神奇的命名空间 ID(如果存在的话),这是我所知道的唯一使用 Boost 的方法。 N.b。这修复了 big-endian 机器的旧 Boost 代码中的错误;如果您需要保留该错误,请将对 boost::endian::native_to_big
的调用改为调用 boost::endian::endian_reverse
。
我正在尝试以这种方式生成 boost::uuids::uuid from boost::compute::detail::sha1:
#include <iostream>
#include "boost/uuid/uuid.hpp"
#include "boost/uuid/uuid_io.hpp"
#include "boost/uuid/string_generator.hpp"
#include "boost/compute/detail/sha1.hpp"
int main(int argc, char* argv[])
{
try
{
boost::compute::detail::sha1 sha1("b888e35f9edf3794760392e1066d69-f43d-452e-8475-a09bae9a2e8500000000-0000-0000-0000-000000000000");
std::string str = sha1;
boost::uuids::uuid uuid = boost::uuids::string_generator()(str); // ERROR HERE!!
}
catch (std::exception& e)
{
std::cerr << "Error occurred: " << e.what() << std::endl;
}
return 0;
}
但是此代码失败并出现错误 Error occurred: invalid uuid string
(见上文)
我正在使用 Visual Studio 2017,Boost 1.67
我的错误在哪里?如何从 boost::compute::detail::sha1
生成 boost::uuids::uuidPS:该代码适用于以前的增强版本。
从任意字符串的 SHA1 散列中获取 UUID 的正确、受支持的方法如下:
#include <string_view>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/name_generator_sha1.hpp>
boost::uuids::uuid uuid_from_string(std::string_view const input) {
static constexpr boost::uuids::uuid ns_id{}; // †null root, change as necessary
return boost::uuids::name_generator_sha1{ns_id}(input.data(), input.size());
}
(std::string_view
用于说明;如果这对您来说不理想,请使用 std::string
或 char const*
或任何合适的内容。)
虽然这是正确的方法,但有两个重要注意事项:
根据 RFC 4122,您需要为您的 UUID 提供命名空间;基本上这是你的 SHA1 散列的盐。 DNS 名称、URL、ISO OID 和 X.500 专有名称都有预定义的名称空间,但由于您的输入似乎与您需要定义的任何名称都不匹配;如标有 † 的行所示,此处使用 null 名称空间进行说明。可以在这个 SO 答案中找到 UUID 名称空间的更详细解释:Generating v5 UUID. What is name and namespace?
此代码的输出与您问题中代码的输出完全不同; iff 您需要输出与旧代码匹配您可以执行以下操作:
#include <cstring> #include <string_view> #include <boost/endian/conversion.hpp> #include <boost/uuid/uuid.hpp> #include <boost/uuid/detail/sha1.hpp> boost::uuids::uuid uuid_from_string_old(std::string_view const input) { boost::uuids::detail::sha1::digest_type digest; { boost::uuids::detail::sha1 h; h.process_bytes(input.data(), input.size()); h.get_digest(digest); } boost::uuids::uuid ret; auto p = ret.begin(); for (std::size_t i{}; i != 4; p += 4, ++i) { auto const d = boost::endian::native_to_big(digest[i]); std::memcpy(p, &d, 4); } return ret; }
这会产生相同的输出,从 this demo 可以看出,使用带有 Boost 1.65.1 的旧代码。这违背了我从未直接使用别人的
detail
命名空间的评论政策,但除非你能找到神奇的命名空间 ID(如果存在的话),这是我所知道的唯一使用 Boost 的方法。 N.b。这修复了 big-endian 机器的旧 Boost 代码中的错误;如果您需要保留该错误,请将对boost::endian::native_to_big
的调用改为调用boost::endian::endian_reverse
。