Index: chrome/browser/chromeos/login/auth/key.cc |
diff --git a/chrome/browser/chromeos/login/auth/key.cc b/chrome/browser/chromeos/login/auth/key.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ab6abd86500843945a3494a6fb07542188f0f651 |
--- /dev/null |
+++ b/chrome/browser/chromeos/login/auth/key.cc |
@@ -0,0 +1,117 @@ |
+// Copyright 2014 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/chromeos/login/auth/key.h" |
+ |
+#include "base/base64.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/string_util.h" |
+#include "crypto/sha2.h" |
+#include "crypto/symmetric_key.h" |
+ |
+namespace chromeos { |
+ |
+namespace { |
+ |
+// Parameters for the transformation to KEY_TYPE_SALTED_AES256_1234. |
+const int kNumIterations = 1234; |
+const int kKeySizeInBits = 256; |
+ |
+} // namespace |
+ |
+Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) { |
+} |
+ |
+Key::Key(const Key& other) : key_type_(other.key_type_), |
+ salt_(other.salt_), |
+ secret_(other.secret_), |
+ label_(other.label_) { |
+} |
+ |
+Key::Key(const std::string& plain_text_password) |
+ : key_type_(KEY_TYPE_PASSWORD_PLAIN), |
+ secret_(plain_text_password) { |
+} |
+ |
+Key::Key(KeyType key_type, const std::string& salt, const std::string& secret) |
+ : key_type_(key_type), |
+ salt_(salt), |
+ secret_(secret) { |
+ |
+} |
+ |
+Key::~Key() { |
+} |
+ |
+bool Key::operator==(const Key& other) const { |
+ return other.key_type_ == key_type_ && |
+ other.salt_ == salt_ && |
+ other.secret_ == secret_ && |
+ other.label_ == label_; |
+} |
+ |
+Key::KeyType Key::GetKeyType() const { |
+ return key_type_; |
+} |
+ |
+const std::string& Key::GetSecret() const { |
+ return secret_; |
+} |
+ |
+const std::string& Key::GetLabel() const { |
+ return label_; |
+} |
+ |
+void Key::SetLabel(const std::string& label) { |
+ label_ = label; |
+} |
+ |
+void Key::ClearSecret() { |
+ secret_.clear(); |
+} |
+ |
+void Key::Transform(KeyType target_key_type, const std::string& salt) { |
+ if (key_type_ != KEY_TYPE_PASSWORD_PLAIN) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ switch (target_key_type) { |
+ case KEY_TYPE_SALTED_SHA256_TOP_HALF: { |
+ // TODO(stevenjb/nkostylev): Handle empty salt gracefully. |
+ CHECK(!salt.empty()); |
+ char hash[crypto::kSHA256Length]; |
+ crypto::SHA256HashString(salt + secret_, &hash, sizeof(hash)); |
+ |
+ // Keep only the first half of the hash for 'weak' hashing so that the |
+ // plain text secret cannot be reconstructed even if the hashing is |
+ // reversed. |
+ secret_ = StringToLowerASCII(base::HexEncode( |
+ reinterpret_cast<const void*>(hash), sizeof(hash) / 2)); |
+ break; |
+ } case KEY_TYPE_SALTED_PBKDF2_AES256_1234: { |
+ scoped_ptr<crypto::SymmetricKey> key( |
+ crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, |
+ secret_, |
+ salt, |
+ kNumIterations, |
+ kKeySizeInBits)); |
+ std::string raw_secret; |
+ key->GetRawKey(&raw_secret); |
+ base::Base64Encode(raw_secret, &secret_); |
+ break; |
+ } default: |
+ // The resulting key will be sent to cryptohomed. It should always be |
+ // hashed. If hashing fails, crash instead of sending a plain-text key. |
+ CHECK(false); |
+ return; |
+ } |
+ |
+ key_type_ = target_key_type; |
+ salt_ = salt; |
+} |
+ |
+} // namespace chromeos |