Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: chrome/browser/metrics/rappord.h

Issue 49753002: RAPPOR implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium 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 #ifndef CHROME_BROWSER_METRICS_RAPPORD_H_
6 #define CHROME_BROWSER_METRICS_RAPPORD_H_
7
8 #include <assert.h>
9 #include <limits.h>
10 #include <math.h>
11
12 #include <bitset>
13 #include <map>
14 #include <string>
15 #include <vector>
16
17 #include "crypto/hmac.h"
18 #include "crypto/random.h"
19 // FIXME(holte) Avoid checkdeps issue.
20 // #include "third_party/smhasher/src/MurmurHash3.h"
21
22 static inline uint32 MurmurHash3String(const std::string& str, uint32 seed) {
23 uint32 output;
24 // MurmurHash3_x86_32(str.data(), str.size(), seed, &output);
25 return output;
26 }
27
28 // NOTE: These were just generated from /dev/urandom. May be unecessary
29 // for murmur hash, or may be better to select carefully to help the
30 // hash function distribute its inputs.
31 static const uint32_t hashSeedCount = 20;
32 static const uint32_t mockHashSeeds[hashSeedCount] = {
33 0xd123957d, 0x6752fc9b, 0xcb6a0102, 0x1a82ea95,
34 0x55cb27bd, 0x0d23a17e, 0xbfb2beac, 0xbabca478,
35 0x6d0b103c, 0x5e98bc37, 0xe73ccb9d, 0xe60c1150,
36 0xa5f070a8, 0x91cc68c2, 0x12c919ff, 0xfec1d371,
37 0x01b6bf4c, 0xbbe5cf2b, 0x6bd30801, 0x292956d3
38 };
39
40
41
42 template <size_t BitCount, size_t HashCount, int lieProbIndex, int pProbIndex,
43 int qProbIndex>
44 class RappordBloomFilter {
45 public:
46 typedef std::bitset<BitCount> bitmap_t;
47 static const size_t MIN_BITMAP_SIZE = sizeof(uint64_t)*CHAR_BIT;
48
49 RappordBloomFilter(const uint32_t seed, const std::string id) :
50 hmac_(crypto::HMAC::SHA256) {
51 if (!hmac_.Init(id)) {
52 abort();
53 };
54 assert(hmac_.DigestLength() > sizeof(uint64_t));
55 hmac_state_ = uint64_t(BitCount * HashCount *
56 lieProbIndex * pProbIndex * qProbIndex * seed);
57
58 const bitmap_t liebits = get_random_bitmap_for_probability_index(
59 lieProbIndex, false);
60 // hard-code that we lie 50%/50% on ones vs zeros
61 lieones_ = liebits & random_bitmap(false);
62 truthbits_ = ~liebits;
63 }
64
65 bitmap_t get(const std::vector<std::string>& strings) {
66 return generate_rappord(get_real_bloombits(strings));
67 }
68
69 bitmap_t get(const std::string str) {
70 return generate_rappord(get_real_bloombits(str));
71 }
72
73 static bitmap_t get_real_bloombits(const std::string& str) {
74 // Get the bits of a bloomfilter for a string
75 assert(BitCount % MIN_BITMAP_SIZE == 0);
76 assert(HashCount < hashSeedCount);
77 bitmap_t bloombits;
78 for (size_t j = 0; j < HashCount; ++j) {
79 uint32_t index = MurmurHash3String(str, mockHashSeeds[j]);
80 bloombits.set(index % BitCount);
81 }
82 return bloombits;
83 }
84
85 static bitmap_t get_real_bloombits(const std::vector<std::string>& strings) {
86 // Get the bits of a bloomfilter for all of the input strings.
87 bitmap_t bloombits;
88 for (size_t i = 0, len = strings.size(); i < len; ++i) {
89 bloombits |= get_real_bloombits(strings[i]);
90 }
91 return bloombits;
92 }
93
94 private:
95 bitmap_t lieones_;
96 bitmap_t truthbits_;
97 crypto::HMAC hmac_;
98 uint64_t hmac_state_;
99
100 // Construct a RAPPORD based on the bits set in the bloomfilter, as well as
101 // the bits for which the current user will deterministally lie zero or one.
102 // Requires: (~truthbits) == liebits == (liezeros | lieones)
103 // where (liezeros & lieones) == 0
104 //
105 const bitmap_t generate_rappord(const bitmap_t& real_bloombits) {
106 const bitmap_t zeros = get_random_bitmap_for_probability_index(
107 pProbIndex, true);
108 const bitmap_t ones = get_random_bitmap_for_probability_index(
109 qProbIndex, true);
110 const bitmap_t onebits = (real_bloombits & truthbits_) | lieones_;
111 return (zeros & (~onebits)) | (ones & onebits);
112 }
113
114 bitmap_t random_bitmap(const bool fresh) {
115 assert(BitCount % MIN_BITMAP_SIZE == 0);
116 bitmap_t bits;
117 for (size_t i = 0; i < BitCount; i += MIN_BITMAP_SIZE) {
118 uint64_t randomBits;
119 assert(MIN_BITMAP_SIZE/CHAR_BIT == sizeof(uint64_t));
120 if (!fresh) {
121 hmacRandBytes(&randomBits);
122 } else {
123 crypto::RandBytes(&randomBits, sizeof(uint64_t));
124 }
125
126 bits <<= MIN_BITMAP_SIZE;
127 bits |= bitmap_t(randomBits);
128 }
129 return bits;
130 }
131
132 void hmacRandBytes(uint64_t* randomBits) {
133 std::string state = bitmap_t(hmac_state_).to_string();
134 if (!hmac_.Sign(state, (unsigned char *) randomBits, sizeof(uint64_t))) {
135 abort();
136 }
137 ++hmac_state_;
138 }
139
140 // TODO(holte): change to template function
141 bitmap_t get_random_bitmap_for_probability_index(
142 int probIndex, const bool fresh) {
143 switch (probIndex) {
144 // 87.5% ones
145 case -8: return ~(random_bitmap(fresh) & random_bitmap(fresh) &
146 random_bitmap(fresh));
147 // 75% ones
148 case -4: return ~(random_bitmap(fresh) & random_bitmap(fresh));
149 // 50% ones
150 case 2: return random_bitmap(fresh);
151 // 25% ones
152 case 4: return random_bitmap(fresh) & random_bitmap(fresh);
153 // 12.5% ones
154 case 8: return random_bitmap(fresh) & random_bitmap(fresh) &
155 random_bitmap(fresh);
156 default:
157 // Invalid probability index "probIndex" for coin flips
158 abort();
159 }
160 }
161 };
162
163 #endif // CHROME_BROWSER_METRICS_RAPPORD_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698