Chromium Code Reviews| Index: chrome/browser/prefs/pref_hash_calculator.cc |
| diff --git a/chrome/browser/prefs/pref_hash_calculator.cc b/chrome/browser/prefs/pref_hash_calculator.cc |
| index 4a787a8a1abb699d8a3447c3a34caf3eee638bb8..e965d2ac31387b26747cf23c7a9db13e0bf06650 100644 |
| --- a/chrome/browser/prefs/pref_hash_calculator.cc |
| +++ b/chrome/browser/prefs/pref_hash_calculator.cc |
| @@ -16,6 +16,32 @@ |
| namespace { |
| +// Calculates an HMAC of |message| using |key|, encoded as a hexadecimal string. |
| +std::string GetDigestString(const std::string& key, |
| + const std::string& message) { |
| + crypto::HMAC hmac(crypto::HMAC::SHA256); |
| + std::vector<uint8> digest(hmac.DigestLength()); |
| + if (!hmac.Init(key) || !hmac.Sign(message, &digest[0], digest.size())) { |
| + NOTREACHED(); |
| + return std::string(); |
| + } |
| + return base::HexEncode(digest.data(), digest.size()); |
| +} |
| + |
| +// Verifies that |digest_string| is a valid HMAC of |message| using |key|. |
| +// |digest_string| must be encoded as a hexadecimal string. |
| +bool VerifyDigestString(const std::string& key, |
| + const std::string& message, |
| + const std::string& digest_string) { |
| + crypto::HMAC hmac(crypto::HMAC::SHA256); |
| + std::vector<uint8> digest; |
| + return base::HexStringToBytes(digest_string, &digest) && |
| + hmac.Init(key) && |
| + hmac.Verify(message, |
| + base::StringPiece(reinterpret_cast<char*>(&digest[0]), |
| + digest.size())); |
| +} |
| + |
| // Renders |value| as a string. |value| may be NULL, in which case the result |
| // is an empty string. |
| std::string ValueAsString(const base::Value* value) { |
| @@ -38,53 +64,63 @@ std::string ValueAsString(const base::Value* value) { |
| } |
| // Common helper for all hash algorithms. |
| -std::string CalculateFromValueAndComponents( |
| - const std::string& seed, |
| +std::string GetMessageFromValueAndComponents( |
| const base::Value* value, |
| const std::vector<std::string>& extra_components) { |
| - static const size_t kSHA256DigestSize = 32; |
| + return JoinString(extra_components, "") + ValueAsString(value); |
| +} |
| - std::string message = JoinString(extra_components, "") + ValueAsString(value); |
| - crypto::HMAC hmac(crypto::HMAC::SHA256); |
| - unsigned char digest[kSHA256DigestSize]; |
| - if (!hmac.Init(seed) || !hmac.Sign(message, digest, arraysize(digest))) { |
| - NOTREACHED(); |
| +// Generates a device ID based on the input device ID. The derived device ID has |
| +// no useful properties beyond those of the input device ID except that it is |
| +// consistent with previous implementations. |
| +std::string GenerateDeviceIdLikePrefMetricsServiceDid( |
| + const std::string& original_device_id) { |
| + if (original_device_id.empty()) |
| return std::string(); |
| - } |
| + return StringToLowerASCII( |
| + GetDigestString(original_device_id, "PrefMetricsService")); |
| +} |
| - return base::HexEncode(digest, arraysize(digest)); |
| +// Verifies a hash using a deprecated hash algorithm. For validating old |
| +// hashes during migration. |
| +bool VerifyLegacyHash(const std::string& seed, |
| + const base::Value* value, |
| + const std::string& digest_string) { |
| + return VerifyDigestString( |
| + seed, |
| + GetMessageFromValueAndComponents(value, std::vector<std::string>()), |
| + digest_string); |
| } |
| } // namespace |
| PrefHashCalculator::PrefHashCalculator(const std::string& seed, |
| const std::string& device_id) |
| - : seed_(seed), device_id_(device_id) {} |
| + : seed_(seed), |
| + device_id_(GenerateDeviceIdLikePrefMetricsServiceDid(device_id)) {} |
| std::string PrefHashCalculator::Calculate(const std::string& path, |
| const base::Value* value) const { |
| - std::vector<std::string> components; |
| - if (!device_id_.empty()) |
| - components.push_back(device_id_); |
| - components.push_back(path); |
| - return CalculateFromValueAndComponents(seed_, value, components); |
| + return GetDigestString(seed_, GetMessage(path, value)); |
| } |
| PrefHashCalculator::ValidationResult PrefHashCalculator::Validate( |
| const std::string& path, |
| const base::Value* value, |
| - const std::string& hash) const { |
| - if (hash == Calculate(path, value)) |
| + const std::string& digest_string) const { |
| + if (VerifyDigestString(seed_, GetMessage(path, value), digest_string)) |
| return VALID; |
| - if (hash == CalculateLegacyHash(path, value)) |
| + if (VerifyLegacyHash(seed_, value, digest_string)) |
|
Ryan Sleevi
2014/01/10 19:24:52
There's a slight cryptographic risk in that you're
|
| return VALID_LEGACY; |
| return INVALID; |
| } |
| -std::string PrefHashCalculator::CalculateLegacyHash( |
| - const std::string& path, const base::Value* value) const { |
| - return CalculateFromValueAndComponents(seed_, |
| - value, |
| - std::vector<std::string>()); |
| +std::string PrefHashCalculator::GetMessage(const std::string& path, |
| + const base::Value* value) const { |
| + std::vector<std::string> components; |
| + if (!device_id_.empty()) |
| + components.push_back(device_id_); |
| + components.push_back(path); |
| + return GetMessageFromValueAndComponents(value, components); |
| } |