2016-09-27 22:01:08 +03:00
|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
2014-08-26 00:44:06 +04:00
|
|
|
#include "cmUuid.h"
|
|
|
|
|
|
|
|
#include "cm_sha2.h"
|
2016-08-17 02:08:13 +03:00
|
|
|
|
2016-04-29 17:53:13 +03:00
|
|
|
#include <cmsys/MD5.h>
|
2016-08-17 02:08:13 +03:00
|
|
|
#include <string.h>
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
cmUuid::cmUuid()
|
|
|
|
{
|
|
|
|
Groups.push_back(4);
|
|
|
|
Groups.push_back(2);
|
|
|
|
Groups.push_back(2);
|
|
|
|
Groups.push_back(2);
|
|
|
|
Groups.push_back(6);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string const& name) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
|
|
|
std::vector<unsigned char> hashInput;
|
|
|
|
this->CreateHashInput(uuidNamespace, name, hashInput);
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
cmsysMD5_s* md5 = cmsysMD5_New();
|
2014-08-26 00:44:06 +04:00
|
|
|
cmsysMD5_Initialize(md5);
|
|
|
|
cmsysMD5_Append(md5, &hashInput[0], int(hashInput.size()));
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
unsigned char digest[16] = { 0 };
|
2014-08-26 00:44:06 +04:00
|
|
|
cmsysMD5_Finalize(md5, digest);
|
|
|
|
|
|
|
|
cmsysMD5_Delete(md5);
|
|
|
|
|
|
|
|
return this->FromDigest(digest, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string const& name) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
|
|
|
std::vector<unsigned char> hashInput;
|
|
|
|
this->CreateHashInput(uuidNamespace, name, hashInput);
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
SHA_CTX* sha = new SHA_CTX;
|
2014-08-26 00:44:06 +04:00
|
|
|
SHA1_Init(sha);
|
|
|
|
SHA1_Update(sha, &hashInput[0], hashInput.size());
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
unsigned char digest[SHA1_DIGEST_LENGTH] = { 0 };
|
2014-08-26 00:44:06 +04:00
|
|
|
SHA1_Final(digest, sha);
|
|
|
|
|
|
|
|
delete sha;
|
|
|
|
|
|
|
|
return this->FromDigest(digest, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string const& name,
|
|
|
|
std::vector<unsigned char>& output) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
|
|
|
output = uuidNamespace;
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!name.empty()) {
|
2014-08-26 00:44:06 +04:00
|
|
|
output.resize(output.size() + name.size());
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
memcpy(&output[0] + uuidNamespace.size(), name.c_str(), name.size());
|
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
}
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
std::string cmUuid::FromDigest(const unsigned char* digest,
|
|
|
|
unsigned char version) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
|
|
|
typedef unsigned char byte_t;
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
byte_t uuid[16] = { 0 };
|
2014-08-26 00:44:06 +04:00
|
|
|
memcpy(uuid, digest, 16);
|
|
|
|
|
|
|
|
uuid[6] &= 0xF;
|
|
|
|
uuid[6] |= byte_t(version << 4);
|
|
|
|
|
|
|
|
uuid[8] &= 0x3F;
|
|
|
|
uuid[8] |= 0x80;
|
|
|
|
|
|
|
|
return this->BinaryToString(uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cmUuid::StringToBinary(std::string const& input,
|
2016-05-16 17:34:04 +03:00
|
|
|
std::vector<unsigned char>& output) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
|
|
|
output.clear();
|
|
|
|
output.reserve(16);
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
if (input.length() != 36) {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
size_t index = 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
for (size_t i = 0; i < this->Groups.size(); ++i) {
|
|
|
|
if (i != 0 && input[index++] != '-') {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
size_t digits = this->Groups[i] * 2;
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!StringToBinaryImpl(input.substr(index, digits), output)) {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
index += digits;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cmUuid::BinaryToString(const unsigned char* input) const
|
|
|
|
{
|
|
|
|
std::string output;
|
|
|
|
|
|
|
|
size_t inputIndex = 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
for (size_t i = 0; i < this->Groups.size(); ++i) {
|
|
|
|
if (i != 0) {
|
2014-08-26 00:44:06 +04:00
|
|
|
output += '-';
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
size_t bytes = this->Groups[i];
|
2016-05-16 17:34:04 +03:00
|
|
|
for (size_t j = 0; j < bytes; ++j) {
|
2014-08-26 00:44:06 +04:00
|
|
|
unsigned char byte = input[inputIndex++];
|
|
|
|
output += this->ByteToHex(byte);
|
|
|
|
}
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cmUuid::ByteToHex(unsigned char byte) const
|
|
|
|
{
|
|
|
|
std::string result;
|
2016-05-16 17:34:04 +03:00
|
|
|
for (int i = 0; i < 2; ++i) {
|
2014-08-26 00:44:06 +04:00
|
|
|
unsigned char rest = byte % 16;
|
|
|
|
byte /= 16;
|
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA));
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
result = c + result;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cmUuid::StringToBinaryImpl(std::string const& input,
|
2016-05-16 17:34:04 +03:00
|
|
|
std::vector<unsigned char>& output) const
|
2014-08-26 00:44:06 +04:00
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (input.size() % 2) {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
2016-05-16 17:34:04 +03:00
|
|
|
for (size_t i = 0; i < input.size(); i += 2) {
|
2014-08-26 00:44:06 +04:00
|
|
|
char c1 = 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!IntFromHexDigit(input[i], c1)) {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
char c2 = 0;
|
2016-05-16 17:34:04 +03:00
|
|
|
if (!IntFromHexDigit(input[i + 1], c2)) {
|
2014-08-26 00:44:06 +04:00
|
|
|
return false;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
output.push_back(char(c1 << 4 | c2));
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2014-08-26 00:44:06 +04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cmUuid::IntFromHexDigit(char input, char& output) const
|
|
|
|
{
|
2016-05-16 17:34:04 +03:00
|
|
|
if (input >= '0' && input <= '9') {
|
2014-08-26 00:44:06 +04:00
|
|
|
output = char(input - '0');
|
|
|
|
return true;
|
2016-08-18 21:36:29 +03:00
|
|
|
}
|
|
|
|
if (input >= 'a' && input <= 'f') {
|
2014-08-26 00:44:06 +04:00
|
|
|
output = char(input - 'a' + 0xA);
|
|
|
|
return true;
|
2016-08-18 21:36:29 +03:00
|
|
|
}
|
|
|
|
if (input >= 'A' && input <= 'F') {
|
2014-08-26 00:44:06 +04:00
|
|
|
output = char(input - 'A' + 0xA);
|
|
|
|
return true;
|
2016-05-16 17:34:04 +03:00
|
|
|
}
|
2016-08-18 21:36:29 +03:00
|
|
|
return false;
|
2014-08-26 00:44:06 +04:00
|
|
|
}
|