Move crypto_helpers from sync to crypto
crypto_helpers only depends on resources in base and is used by sync and
password_manager.
BUG=
TEST=
Review URL: http://codereview.chromium.org/6873156
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84223 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/rand_util.cc b/base/rand_util.cc
index b823fa0..4140e9a 100644
--- a/base/rand_util.cc
+++ b/base/rand_util.cc
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
+#include "base/string_util.h"
namespace base {
@@ -47,19 +48,19 @@
return base::RandUint64() % max;
}
-std::string RandBytesAsString(size_t length) {
- const size_t kBitsPerChar = 8;
- const int kCharsPerInt64 = sizeof(uint64)/sizeof(char);
-
- std::string result(length, '\0');
- uint64 entropy = 0;
- for (size_t i = 0; i < result.size(); ++i) {
- if (i % kCharsPerInt64 == 0)
- entropy = RandUint64();
- result[i] = static_cast<char>(entropy);
- entropy >>= kBitsPerChar;
+void RandBytes(void* output, size_t output_length) {
+ uint64 random_int;
+ size_t random_int_size = sizeof(random_int);
+ for (size_t i = 0; i < output_length; i += random_int_size) {
+ random_int = base::RandUint64();
+ size_t copy_count = std::min(output_length - i, random_int_size);
+ memcpy(((uint8*)output) + i, &random_int, copy_count);
}
+}
+std::string RandBytesAsString(size_t length) {
+ std::string result;
+ RandBytes(WriteInto(&result, length + 1), length);
return result;
}
diff --git a/base/rand_util.h b/base/rand_util.h
index d10cc8b..6bfbcb4 100644
--- a/base/rand_util.h
+++ b/base/rand_util.h
@@ -33,7 +33,14 @@
// the range [0, 1). Thread-safe.
BASE_API double BitsToOpenEndedUnitInterval(uint64 bits);
-// Returns a random string of the specified length.
+// Fills |output_length| bytes of |output| with cryptographically strong random
+// data.
+BASE_API void RandBytes(void* output, size_t output_length);
+
+// Fills a string of length |length| with with cryptographically strong random
+// data and returns it.
+//
+// Not that this is a variation of |RandBytes| with a different return type.
BASE_API std::string RandBytesAsString(size_t length);
} // namespace base
diff --git a/base/rand_util_unittest.cc b/base/rand_util_unittest.cc
index 3bdb815..d7fa37af 100644
--- a/base/rand_util_unittest.cc
+++ b/base/rand_util_unittest.cc
@@ -28,6 +28,19 @@
EXPECT_LE(0.0, number);
}
+TEST(RandUtilTest, RandBytes) {
+ const size_t buffer_size = 145;
+ char buffer[buffer_size];
+ memset(buffer, 0, buffer_size);
+ base::RandBytes(buffer, buffer_size);
+ char accumulator = 0;
+ for(size_t i = 0; i < buffer_size; ++i)
+ accumulator |= buffer[i];
+ // In theory this test can fail, but it won't before the universe dies of
+ // heat death.
+ EXPECT_NE(0, accumulator);
+}
+
TEST(RandUtilTest, RandBytesAsString) {
std::string random_string = base::RandBytesAsString(0);
EXPECT_EQ(0U, random_string.size());
diff --git a/chrome/browser/password_manager/encryptor_password_mac.mm b/chrome/browser/password_manager/encryptor_password_mac.mm
index a955043..ffdf24ce 100644
--- a/chrome/browser/password_manager/encryptor_password_mac.mm
+++ b/chrome/browser/password_manager/encryptor_password_mac.mm
@@ -7,7 +7,7 @@
#import <Security/Security.h>
#include "chrome/browser/keychain_mac.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
+#include "chrome/common/random.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
@@ -18,7 +18,7 @@
std::string AddRandomPasswordToKeychain(const MacKeychain& keychain,
const std::string& service_name,
const std::string& account_name) {
- std::string password = Generate128BitRandomHexString();
+ std::string password = Generate128BitRandomBase64String();
void* password_data =
const_cast<void*>(static_cast<const void*>(password.data()));
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 3e17d6f3..6cf7408 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -62,7 +62,6 @@
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/nigori_util.h"
#include "chrome/browser/sync/syncable/syncable.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/deprecated/event_sys.h"
#include "chrome/common/net/gaia/gaia_authenticator.h"
diff --git a/chrome/browser/sync/syncable/directory_backing_store.cc b/chrome/browser/sync/syncable/directory_backing_store.cc
index 7f5721e6..7983c73 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -24,7 +24,7 @@
#include "chrome/browser/sync/protocol/sync.pb.h"
#include "chrome/browser/sync/syncable/syncable-inl.h"
#include "chrome/browser/sync/syncable/syncable_columns.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
+#include "chrome/common/random.h"
#include "chrome/common/sqlite_utils.h"
#include "third_party/sqlite/sqlite3.h"
@@ -61,7 +61,7 @@
}
string GenerateCacheGUID() {
- return Generate128BitRandomHexString();
+ return Generate128BitRandomBase64String();
}
} // namespace
diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
index 0674457ec..9a83458 100644
--- a/chrome/browser/sync/syncable/syncable.cc
+++ b/chrome/browser/sync/syncable/syncable.cc
@@ -49,7 +49,6 @@
#include "chrome/browser/sync/syncable/syncable_changes_version.h"
#include "chrome/browser/sync/syncable/syncable_columns.h"
#include "chrome/browser/sync/syncable/syncable_enum_conversions.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
#include "chrome/common/deprecated/event_sys-inl.h"
#include "net/base/escape.h"
diff --git a/chrome/browser/sync/util/crypto_helpers.cc b/chrome/browser/sync/util/crypto_helpers.cc
deleted file mode 100644
index 36c5586..0000000
--- a/chrome/browser/sync/util/crypto_helpers.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2010 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 "chrome/browser/sync/util/crypto_helpers.h"
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/base64.h"
-#include "base/rand_util.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-
-using std::string;
-using std::vector;
-
-MD5Calculator::MD5Calculator() {
- MD5Init(&context_);
-}
-
-MD5Calculator::~MD5Calculator() {}
-
-void MD5Calculator::AddData(const unsigned char* data, int length) {
- CHECK(bin_digest_.empty());
- MD5Update(&context_, data, length);
-}
-
-void MD5Calculator::CalcDigest() {
- if (bin_digest_.empty()) {
- MD5Digest digest;
- MD5Final(&digest, &context_);
- bin_digest_.assign(digest.a, digest.a + arraysize(digest.a));
- }
-}
-
-const vector<uint8>& MD5Calculator::GetDigest() {
- CalcDigest();
- return bin_digest_;
-}
-
-std::string MD5Calculator::GetHexDigest() {
- CalcDigest();
- string hex = base::HexEncode(reinterpret_cast<char*>(&bin_digest_.front()),
- bin_digest_.size());
- StringToLowerASCII(&hex);
- return hex;
-}
-
-void GetRandomBytes(char* output, int output_length) {
- uint64 random_int;
- const char* random_int_bytes = reinterpret_cast<const char*>(&random_int);
- int random_int_size = sizeof(random_int);
- for (int i = 0; i < output_length; i += random_int_size) {
- random_int = base::RandUint64();
- int copy_count = std::min(output_length - i, random_int_size);
- memcpy(output + i, random_int_bytes, copy_count);
- }
-}
-
-string Generate128BitRandomHexString() {
- const int kNumberBytes = 128 / 8;
- std::string random_bytes(kNumberBytes, ' ');
- GetRandomBytes(&random_bytes[0], kNumberBytes);
- std::string base64_encoded_bytes;
- base::Base64Encode(random_bytes, &base64_encoded_bytes);
- return base64_encoded_bytes;
-}
diff --git a/chrome/browser/sync/util/crypto_helpers.h b/chrome/browser/sync/util/crypto_helpers.h
deleted file mode 100644
index 34b36f4..0000000
--- a/chrome/browser/sync/util/crypto_helpers.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
-#define CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-// An object to handle calculation of MD5 sums.
-#include "base/basictypes.h"
-#include "base/md5.h"
-#include "base/port.h"
-
-class MD5Calculator {
- protected:
- MD5Context context_;
- std::vector<uint8> bin_digest_;
-
- void CalcDigest();
- public:
- MD5Calculator();
- ~MD5Calculator();
- void AddData(const uint8* data, int length);
- void AddData(const char* data, int length) {
- AddData(reinterpret_cast<const uint8*>(data), length);
- }
- std::string GetHexDigest();
- const std::vector<uint8>& GetDigest();
- private:
- DISALLOW_COPY_AND_ASSIGN(MD5Calculator);
-};
-
-void GetRandomBytes(char* output, int output_length);
-std::string Generate128BitRandomHexString();
-
-#endif // CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
diff --git a/chrome/browser/sync/util/crypto_helpers_unittest.cc b/chrome/browser/sync/util/crypto_helpers_unittest.cc
deleted file mode 100644
index 7be1270..0000000
--- a/chrome/browser/sync/util/crypto_helpers_unittest.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2009 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 "chrome/browser/sync/util/crypto_helpers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(ChecksumTest, MD5ChecksumTest) {
- uint8 buffer[256];
- for (unsigned int i = 0; i < arraysize(buffer); ++i) {
- buffer[i] = i;
- }
- MD5Calculator md5;
- md5.AddData(buffer, arraysize(buffer));
- std::string checksum("e2c865db4162bed963bfaa9ef6ac18f0");
- ASSERT_EQ(checksum, md5.GetHexDigest());
-}
-
-TEST(CryptoHelpers, GetRandomBytes) {
- for (int i = 1; i < 25; ++i) {
- std::string random_bytes(i+1, ' ');
- do {
- GetRandomBytes(&random_bytes[0], i);
- ASSERT_EQ(random_bytes[i], ' ');
- } while (random_bytes[i - 1] == ' ');
- }
-}
diff --git a/chrome/browser/sync/util/user_settings.cc b/chrome/browser/sync/util/user_settings.cc
index d49a071..b842c43 100644
--- a/chrome/browser/sync/util/user_settings.cc
+++ b/chrome/browser/sync/util/user_settings.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
//
@@ -18,10 +18,12 @@
#include <vector>
#include "base/file_util.h"
+#include "base/md5.h"
+#include "base/rand_util.h"
#include "base/string_util.h"
#include "chrome/browser/sync/syncable/directory_manager.h" // For migration.
-#include "chrome/browser/sync/util/crypto_helpers.h"
#include "chrome/browser/sync/util/data_encryption.h"
+#include "chrome/common/random.h"
#include "chrome/common/sqlite_utils.h"
using std::numeric_limits;
@@ -166,7 +168,7 @@
SQLStatement statement;
statement.prepare(dbhandle,
"INSERT INTO client_id values ( ? )");
- statement.bind_string(0, Generate128BitRandomHexString());
+ statement.bind_string(0, Generate128BitRandomBase64String());
if (SQLITE_DONE != statement.step()) {
LOG(FATAL) << "INSERT INTO client_id\n" << sqlite3_errmsg(dbhandle);
}
@@ -270,13 +272,12 @@
// We use 10 bits of data from the MD5 digest as the hash.
const int32 kHashMask = 0x3FF;
-int32 GetHashFromDigest(const vector<uint8>& digest) {
+int32 GetHashFromDigest(MD5Digest& digest) {
int32 hash = 0;
int32 mask = kHashMask;
- for (vector<uint8>::const_iterator i = digest.begin(); i != digest.end();
- ++i) {
+ for (size_t i = 0; i < sizeof(digest.a); ++i) {
hash = hash << 8;
- hash = hash | (*i & kHashMask);
+ hash = hash | (digest.a[i] & kHashMask);
mask = mask >> 8;
if (0 == mask)
break;
@@ -351,12 +352,16 @@
const string& password) {
// Save one-way hashed password:
char binary_salt[kSaltSize];
- GetRandomBytes(binary_salt, sizeof(binary_salt));
+ base::RandBytes(binary_salt, sizeof(binary_salt));
const string salt = APEncode(string(binary_salt, sizeof(binary_salt)));
- MD5Calculator md5;
- md5.AddData(salt.data(), salt.size());
- md5.AddData(password.data(), password.size());
+ MD5Context md5_context;
+ MD5Init(&md5_context);
+ MD5Update(&md5_context, salt.data(), salt.size());
+ MD5Update(&md5_context, password.data(), password.size());
+ MD5Digest md5_digest;
+ MD5Final(&md5_digest, &md5_context);
+
ScopedDBHandle dbhandle(this);
SQLTransaction transaction(dbhandle.get());
transaction.BeginExclusive();
@@ -367,7 +372,7 @@
" values ( ?, ?, ? )");
statement.bind_string(0, email);
statement.bind_string(1, PASSWORD_HASH);
- statement.bind_int(2, GetHashFromDigest(md5.GetDigest()));
+ statement.bind_int(2, GetHashFromDigest(md5_digest));
if (SQLITE_DONE != statement.step()) {
LOG(FATAL) << sqlite3_errmsg(dbhandle.get());
}
@@ -413,10 +418,13 @@
CHECK(SQLITE_DONE == query_result);
if (salt.empty() || hash == kInvalidHash)
return false;
- MD5Calculator md5;
- md5.AddData(salt.data(), salt.size());
- md5.AddData(password.data(), password.size());
- return hash == GetHashFromDigest(md5.GetDigest());
+ MD5Context md5_context;
+ MD5Init(&md5_context);
+ MD5Update(&md5_context, salt.data(), salt.size());
+ MD5Update(&md5_context, password.data(), password.size());
+ MD5Digest md5_digest;
+ MD5Final(&md5_digest, &md5_context);
+ return hash == GetHashFromDigest(md5_digest);
}
void UserSettings::SwitchUser(const string& username) {
diff --git a/chrome/browser/sync/util/user_settings_win.cc b/chrome/browser/sync/util/user_settings_win.cc
index 94090ac..d2b0447 100644
--- a/chrome/browser/sync/util/user_settings_win.cc
+++ b/chrome/browser/sync/util/user_settings_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -7,7 +7,6 @@
#include <string>
#include "base/logging.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
#include "chrome/browser/sync/util/data_encryption.h"
#include "chrome/common/sqlite_utils.h"
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 9bd14c6..2af5f7a 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -626,8 +626,6 @@
'browser/sync/syncable/syncable_id.h',
'browser/sync/syncable/syncable_enum_conversions.cc',
'browser/sync/syncable/syncable_enum_conversions.h',
- 'browser/sync/util/crypto_helpers.cc',
- 'browser/sync/util/crypto_helpers.h',
'browser/sync/util/cryptographer.cc',
'browser/sync/util/cryptographer.h',
'browser/sync/util/dbgq.h',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index d488416..e50fbc9 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -211,6 +211,8 @@
'common/pref_store.cc',
'common/pref_store.h',
'common/print_messages.h',
+ 'common/random.cc',
+ 'common/random.h',
'common/remoting/chromoting_host_info.cc',
'common/remoting/chromoting_host_info.h',
'common/render_messages.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ed473fc..3285adb8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1827,6 +1827,7 @@
'common/net/gaia/gaia_oauth_client_unittest.cc',
'common/net/gaia/google_service_auth_error_unittest.cc',
'common/net/url_fetcher_unittest.cc',
+ 'common/random_unittest.cc',
'common/service_process_util_unittest.cc',
'common/switch_utils_unittest.cc',
'common/thumbnail_score_unittest.cc',
@@ -2970,7 +2971,6 @@
'browser/sync/syncable/syncable_enum_conversions_unittest.cc',
'browser/sync/syncable/syncable_id_unittest.cc',
'browser/sync/syncable/syncable_unittest.cc',
- 'browser/sync/util/crypto_helpers_unittest.cc',
'browser/sync/util/data_encryption_unittest.cc',
'browser/sync/util/extensions_activity_monitor_unittest.cc',
'browser/sync/util/protobuf_unittest.cc',
diff --git a/chrome/common/random.cc b/chrome/common/random.cc
new file mode 100644
index 0000000..303d296
--- /dev/null
+++ b/chrome/common/random.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2011 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 "chrome/common/random.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/rand_util.h"
+
+std::string Generate128BitRandomBase64String() {
+ const int kNumberBytes = 128 / 8;
+ std::string base64_encoded_bytes;
+ base::Base64Encode(base::RandBytesAsString(kNumberBytes),
+ &base64_encoded_bytes);
+ return base64_encoded_bytes;
+}
diff --git a/chrome/common/random.h b/chrome/common/random.h
new file mode 100644
index 0000000..0ad538f
--- /dev/null
+++ b/chrome/common/random.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_COMMON_RANDOM_H_
+#define CHROME_COMMON_RANDOM_H_
+#pragma once
+
+#include <string>
+
+// Generate128BitRandomBase64String returns a string of length 24 containing
+// cryptographically strong random data encoded in base64.
+std::string Generate128BitRandomBase64String();
+
+#endif // CHROME_COMMON_RANDOM_H_
diff --git a/chrome/common/random_unittest.cc b/chrome/common/random_unittest.cc
new file mode 100644
index 0000000..c1843e0
--- /dev/null
+++ b/chrome/common/random_unittest.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
+
+#include "chrome/common/random.h"
+
+TEST(SyncRandomTest, Generate128BitRandomBase64String) {
+ std::string random_string = Generate128BitRandomBase64String();
+ EXPECT_EQ(24U, random_string.size());
+ char accumulator = 0;
+ for (size_t i = 0; i < random_string.size(); ++i)
+ accumulator |= random_string[i];
+ // In theory this test can fail, but it won't before the universe dies of
+ // heat death.
+ EXPECT_NE(0, accumulator);
+}
diff --git a/ppapi/shared_impl/crypto_impl.cc b/ppapi/shared_impl/crypto_impl.cc
index 6295bb2..f8e4aa2 100644
--- a/ppapi/shared_impl/crypto_impl.cc
+++ b/ppapi/shared_impl/crypto_impl.cc
@@ -11,14 +11,7 @@
// static
void CryptoImpl::GetRandomBytes(char* buffer, uint32_t num_bytes) {
- // Note: this is a copy of WebKitClientImpl::cryptographicallyRandomValues.
- uint64 bytes = 0;
- for (uint32_t i = 0; i < num_bytes; ++i) {
- uint32_t offset = i % sizeof(bytes);
- if (!offset)
- bytes = base::RandUint64();
- buffer[i] = reinterpret_cast<char*>(&bytes)[offset];
- }
+ base::RandBytes(buffer, num_bytes);
}
} // namespace shared_impl
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index b2dd53a8..882cb42 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -451,13 +451,7 @@
void WebKitClientImpl::cryptographicallyRandomValues(
unsigned char* buffer, size_t length) {
- uint64 bytes = 0;
- for (size_t i = 0; i < length; ++i) {
- size_t offset = i % sizeof(bytes);
- if (!offset)
- bytes = base::RandUint64();
- buffer[i] = reinterpret_cast<unsigned char*>(&bytes)[offset];
- }
+ base::RandBytes(buffer, length);
}
void WebKitClientImpl::setSharedTimerFiredFunction(void (*func)()) {