1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "binary_data_utils.h"
6 
7 #include <openssl/md5.h>
8 #include <sys/stat.h>
9 
10 #include <cstddef>
11 #include <cstdlib>
12 #include <cstring>
13 #include <fstream>
14 #include <iomanip>
15 
16 #include "base/logging.h"
17 #include "base/macros.h"
18 
19 namespace {
20 
21 // Number of hex digits in a byte.
22 const int kNumHexDigitsInByte = 2;
23 
24 }  // namespace
25 
26 namespace quipper {
27 
28 static uint64_t Md5Prefix(const unsigned char* data,
29                           unsigned long length) {
30   uint64_t digest_prefix = 0;
31   unsigned char digest[MD5_DIGEST_LENGTH + 1];
32 
33   MD5(data, length, digest);
34   // We need 64-bits / # of bits in a byte.
35   std::stringstream ss;
36   for (size_t i = 0; i < sizeof(uint64_t); i++)
37     // The setw(2) and setfill('0') calls are needed to make sure we output 2
38     // hex characters for every 8-bits of the hash.
39     ss << std::hex << std::setw(2) << std::setfill('0')
40        << static_cast<unsigned int>(digest[i]);
41   ss >> digest_prefix;
42   return digest_prefix;
43 }
44 
45 uint64_t Md5Prefix(const string& input) {
46   auto data = reinterpret_cast<const unsigned char*>(input.data());
47   return Md5Prefix(data, input.size());
48 }
49 
50 uint64_t Md5Prefix(const std::vector<char>& input) {
51   auto data = reinterpret_cast<const unsigned char*>(input.data());
52   return Md5Prefix(data, input.size());
53 }
54 
55 string RawDataToHexString(const u8* array, size_t length) {
56   // Convert the bytes to hex digits one at a time.
57   // There will be kNumHexDigitsInByte hex digits, and 1 char for NUL.
58   char buffer[kNumHexDigitsInByte + 1];
59   string result = "";
60   for (size_t i = 0; i < length; ++i) {
61     snprintf(buffer, sizeof(buffer), "%02x", array[i]);
62     result += buffer;
63   }
64   return result;
65 }
66 
67 string RawDataToHexString(const string& str) {
68   return RawDataToHexString(reinterpret_cast<const u8*>(str.data()),
69                             str.size());
70 }
71 
72 bool HexStringToRawData(const string& str, u8* array, size_t length) {
73   const int kHexRadix = 16;
74   char* err;
75   // Loop through kNumHexDigitsInByte characters at a time (to get one byte)
76   // Stop when there are no more characters, or the array has been filled.
77   for (size_t i = 0; (i + 1) * kNumHexDigitsInByte <= str.size() && i < length;
78        ++i) {
79     string one_byte = str.substr(i * kNumHexDigitsInByte, kNumHexDigitsInByte);
80     array[i] = strtol(one_byte.c_str(), &err, kHexRadix);
81     if (*err) return false;
82   }
83   return true;
84 }
85 
86 }  // namespace quipper
87