1 // Copyright 2014 The Chromium Authors
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 "base/metrics/metrics_hashes.h"
6
7 #include <string.h>
8
9 #include "base/check_op.h"
10 #include "base/hash/md5.h"
11 #include "base/hash/sha1.h"
12 #include "base/sys_byteorder.h"
13
14 namespace base {
15 namespace {
16
17 // Converts the 8-byte prefix of an MD5 hash into a uint64_t value.
DigestToUInt64(const base::MD5Digest & digest)18 inline uint64_t DigestToUInt64(const base::MD5Digest& digest) {
19 uint64_t value;
20 DCHECK_GE(sizeof(digest.a), sizeof(value));
21 memcpy(&value, digest.a, sizeof(value));
22 return base::NetToHost64(value);
23 }
24
25 // Converts the 4-byte prefix of an MD5 hash into a uint32_t value.
DigestToUInt32(const base::MD5Digest & digest)26 inline uint32_t DigestToUInt32(const base::MD5Digest& digest) {
27 uint32_t value;
28 DCHECK_GE(sizeof(digest.a), sizeof(value));
29 memcpy(&value, digest.a, sizeof(value));
30 return base::NetToHost32(value);
31 }
32
33 } // namespace
34
HashMetricName(base::StringPiece name)35 uint64_t HashMetricName(base::StringPiece name) {
36 // Corresponding Python code for quick look up:
37 //
38 // import struct
39 // import hashlib
40 // struct.unpack('>Q', hashlib.md5(name.encode('utf-8')).digest()[:8])[0]
41 //
42 base::MD5Digest digest;
43 base::MD5Sum(name.data(), name.size(), &digest);
44 return DigestToUInt64(digest);
45 }
46
HashMetricNameAs32Bits(base::StringPiece name)47 uint32_t HashMetricNameAs32Bits(base::StringPiece name) {
48 base::MD5Digest digest;
49 base::MD5Sum(name.data(), name.size(), &digest);
50 return DigestToUInt32(digest);
51 }
52
HashFieldTrialName(base::StringPiece name)53 uint32_t HashFieldTrialName(base::StringPiece name) {
54 // SHA-1 is designed to produce a uniformly random spread in its output space,
55 // even for nearly-identical inputs.
56 unsigned char sha1_hash[base::kSHA1Length];
57 base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(name.data()),
58 name.size(), sha1_hash);
59
60 uint32_t bits;
61 static_assert(sizeof(bits) < sizeof(sha1_hash), "more data required");
62 memcpy(&bits, sha1_hash, sizeof(bits));
63
64 return base::ByteSwapToLE32(bits);
65 }
66
67 } // namespace base
68