Index: components/rappor/byte_vector_utils.cc |
diff --git a/components/rappor/byte_vector_utils.cc b/components/rappor/byte_vector_utils.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c6db9287bd5e1a564ad81cc246d11629171583d5 |
--- /dev/null |
+++ b/components/rappor/byte_vector_utils.cc |
@@ -0,0 +1,105 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/rappor/byte_vector_utils.h" |
+ |
+#include <string> |
+ |
+#include "base/logging.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "crypto/hmac.h" |
+#include "crypto/random.h" |
+ |
+namespace rappor { |
+ |
+ByteVector* ByteVectorAnd(ByteVector* lhs, const ByteVector& rhs) { |
+ DCHECK_EQ(lhs->size(), rhs.size()); |
+ for (size_t i = 0, len = rhs.size(); i < len; i++) { |
+ (*lhs)[i] = (*lhs)[i] & rhs[i]; |
+ } |
+ return lhs; |
+} |
+ |
+ByteVector* ByteVectorOr(ByteVector* lhs, const ByteVector& rhs) { |
+ DCHECK_EQ(lhs->size(), rhs.size()); |
+ for (size_t i = 0, len = rhs.size(); i < len; i++) { |
+ (*lhs)[i] = (*lhs)[i] | rhs[i]; |
+ } |
+ return lhs; |
+} |
+ |
+ByteVector* ByteVectorMerge(ByteVector* lhs, |
+ const ByteVector& rhs, |
+ const ByteVector& mask) { |
+ DCHECK_EQ(lhs->size(), rhs.size()); |
+ for (size_t i = 0, len = rhs.size(); i < len; i++) { |
+ (*lhs)[i] = ((*lhs)[i] & ~mask[i]) | (rhs[i] & mask[i]); |
+ } |
+ return lhs; |
+} |
+ |
+ByteVectorGenerator::ByteVectorGenerator(size_t byte_count) |
+ : byte_count_(byte_count) {} |
+ |
+uint8_t ByteVectorGenerator::RandByte() { |
+ uint8_t random_bits; |
+ crypto::RandBytes(&random_bits, sizeof(uint8_t)); |
+ return random_bits; |
+} |
+ |
+ByteVector ByteVectorGenerator::GetRandomByteVector() { |
+ ByteVector bytes(byte_count_); |
+ for (size_t i = 0; i < byte_count_; i++) { |
+ bytes[i] = RandByte(); |
+ } |
+ return bytes; |
+} |
+ |
+ByteVector ByteVectorGenerator::GetWeightedRandomByteVector( |
+ Probability probability) { |
+ ByteVector bytes = GetRandomByteVector(); |
+ switch (probability) { |
+ case PROBABILITY_87_5: |
+ return *ByteVectorOr(ByteVectorOr(&bytes, GetRandomByteVector()), |
+ GetRandomByteVector()); |
+ case PROBABILITY_75: |
+ return *ByteVectorOr(&bytes, GetRandomByteVector()); |
+ case PROBABILITY_50: |
+ return bytes; |
+ case PROBABILITY_25: |
+ return *ByteVectorAnd(&bytes, GetRandomByteVector()); |
+ case PROBABILITY_12_5: |
+ return *ByteVectorAnd(ByteVectorAnd(&bytes, GetRandomByteVector()), |
+ GetRandomByteVector()); |
+ default: |
+ // Invalid probability for coin flips |
+ abort(); |
+ } |
+} |
+ |
+HmacByteVectorGenerator::HmacByteVectorGenerator(size_t byte_count, |
+ const std::string& secret) |
+ : ByteVectorGenerator(byte_count), hmac_(crypto::HMAC::SHA256) { |
+ // A completely arbitrary value for the initial value of an |
+ // HmacByteVectorGenerator's state. The initial digits of pi. |
+ const uint64_t kHmacInitialState = 3141592653589793; |
+ |
+ if (!hmac_.Init(secret)) { |
+ abort(); |
Alexei Svitkine (slow)
2014/01/09 19:23:09
Don't use abort() in Chrome code. You probably wan
Steven Holte
2014/01/09 22:03:01
Done.
|
+ }; |
+ assert(hmac_.DigestLength() > sizeof(uint64_t)); |
+ hmac_state_ = kHmacInitialState; |
+} |
+ |
+uint8_t HmacByteVectorGenerator::RandByte() { |
+ uint8_t random_bits; |
+ std::string state = base::Uint64ToString(hmac_state_); |
+ if (!hmac_.Sign(state, &random_bits, sizeof(uint8_t))) { |
+ abort(); |
+ } |
+ ++hmac_state_; |
+ return random_bits; |
+} |
+ |
+} // namespace rappor |