diff options
author | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-04 21:39:27 +0000 |
---|---|---|
committer | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-04 21:39:27 +0000 |
commit | e344ead6eddc342c1d3b1684db0bc6f45852c85a (patch) | |
tree | f0c4bfc98c83f61f447c3d518b2209de0cc009a8 /chrome/browser | |
parent | 461f028ab0acdd69a5af64cf45c84e91eb41396c (diff) | |
download | chromium_src-e344ead6eddc342c1d3b1684db0bc6f45852c85a.zip chromium_src-e344ead6eddc342c1d3b1684db0bc6f45852c85a.tar.gz chromium_src-e344ead6eddc342c1d3b1684db0bc6f45852c85a.tar.bz2 |
Let the Nigori client import and export raw encryption keys.
BUG=48701
TEST=NigoriTest.*
Review URL: http://codereview.chromium.org/3013047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54970 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/sync/util/cryptographer.cc | 18 | ||||
-rw-r--r-- | chrome/browser/sync/util/nigori.cc | 38 | ||||
-rw-r--r-- | chrome/browser/sync/util/nigori.h | 21 | ||||
-rw-r--r-- | chrome/browser/sync/util/nigori_unittest.cc | 82 |
4 files changed, 121 insertions, 38 deletions
diff --git a/chrome/browser/sync/util/cryptographer.cc b/chrome/browser/sync/util/cryptographer.cc index f323d17..7a5e173 100644 --- a/chrome/browser/sync/util/cryptographer.cc +++ b/chrome/browser/sync/util/cryptographer.cc @@ -83,8 +83,10 @@ bool Cryptographer::AddKey(const KeyParams& params) { DCHECK(NULL == pending_keys_.get()); // Create the new Nigori and make it the default encryptor. - scoped_ptr<Nigori> nigori(new Nigori(params.hostname)); - if (!nigori->Init(params.username, params.password)) { + scoped_ptr<Nigori> nigori(new Nigori); + if (!nigori->InitByDerivation(params.hostname, + params.username, + params.password)) { NOTREACHED(); // Invalid username or password. return false; } @@ -115,8 +117,10 @@ void Cryptographer::SetPendingKeys(const sync_pb::EncryptedData& encrypted) { } bool Cryptographer::DecryptPendingKeys(const KeyParams& params) { - Nigori nigori(params.hostname); - if (!nigori.Init(params.username, params.password)) { + Nigori nigori; + if (!nigori.InitByDerivation(params.hostname, + params.username, + params.password)) { NOTREACHED(); return false; } @@ -142,8 +146,10 @@ void Cryptographer::InstallKeys(const std::string& default_key_name, const sync_pb::NigoriKey key = bag.key(i); // Only use this key if we don't already know about it. if (nigoris_.end() == nigoris_.find(key.name())) { - scoped_ptr<Nigori> new_nigori(new Nigori(key.hostname())); - if (!new_nigori->Init(key.username(), key.password())) { + scoped_ptr<Nigori> new_nigori(new Nigori); + if (!new_nigori->InitByDerivation(key.hostname(), + key.username(), + key.password())) { NOTREACHED(); continue; } diff --git a/chrome/browser/sync/util/nigori.cc b/chrome/browser/sync/util/nigori.cc index 01de18d..33d3915 100644 --- a/chrome/browser/sync/util/nigori.cc +++ b/chrome/browser/sync/util/nigori.cc @@ -61,19 +61,21 @@ class NigoriStream { // static const char Nigori::kSaltSalt[] = "saltsalt"; -Nigori::Nigori(const std::string& hostname) - : hostname_(hostname) { +Nigori::Nigori() { } Nigori::~Nigori() { } -bool Nigori::Init(const std::string& username, const std::string& password) { +bool Nigori::InitByDerivation(const std::string& hostname, + const std::string& username, + const std::string& password) { + hostname_ = hostname; username_ = username; password_ = password; NigoriStream salt_password; - salt_password << username << hostname_; + salt_password << username << hostname; // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8) scoped_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword( @@ -105,6 +107,22 @@ bool Nigori::Init(const std::string& username, const std::string& password) { return true; } +bool Nigori::InitByImport(const std::string& user_key, + const std::string& encryption_key, + const std::string& mac_key) { + user_key_.reset(SymmetricKey::Import(SymmetricKey::AES, user_key)); + DCHECK(user_key_.get()); + + encryption_key_.reset(SymmetricKey::Import(SymmetricKey::AES, + encryption_key)); + DCHECK(encryption_key_.get()); + + mac_key_.reset(SymmetricKey::Import(SymmetricKey::HMAC_SHA1, mac_key)); + DCHECK(mac_key_.get()); + + return user_key_.get() && encryption_key_.get() && mac_key_.get(); +} + // Permute[Kenc,Kmac](type || name) bool Nigori::Permute(Type type, const std::string& name, std::string* permuted) const { @@ -228,4 +246,16 @@ bool Nigori::Decrypt(const std::string& encrypted, std::string* value) const { return true; } +bool Nigori::ExportKeys(std::string* user_key, + std::string* encryption_key, + std::string* mac_key) const { + DCHECK(user_key); + DCHECK(encryption_key); + DCHECK(mac_key); + + return user_key_->GetRawKey(user_key) && + encryption_key_->GetRawKey(encryption_key) && + mac_key_->GetRawKey(mac_key); +} + } // namespace browser_sync diff --git a/chrome/browser/sync/util/nigori.h b/chrome/browser/sync/util/nigori.h index 4b9b2fa..3a4cb04 100644 --- a/chrome/browser/sync/util/nigori.h +++ b/chrome/browser/sync/util/nigori.h @@ -28,13 +28,19 @@ class Nigori { Password = 1, }; - // Creates a Nigori client for communicating with |hostname|. Note that - // |hostname| is used to derive the keys used to encrypt and decrypt data. - explicit Nigori(const std::string& hostname); + Nigori(); virtual ~Nigori(); - // Initialize the client with the supplied |username| and |password|. - bool Init(const std::string& username, const std::string& password); + // Initialize the client with the given |hostname|, |username| and |password|. + bool InitByDerivation(const std::string& hostname, + const std::string& username, + const std::string& password); + + // Initialize the client by importing the given keys instead of deriving new + // ones. + bool InitByImport(const std::string& user_key, + const std::string& encryption_key, + const std::string& mac_key); // Derives a secure lookup name from |type| and |name|. If |hostname|, // |username| and |password| are kept constant, a given |type| and |name| pair @@ -50,6 +56,11 @@ class Nigori { // encoded. bool Decrypt(const std::string& value, std::string* decrypted) const; + // Exports the raw derived keys. + bool ExportKeys(std::string* user_key, + std::string* encryption_key, + std::string* mac_key) const; + // The next three getters return the parameters used to initialize the keys. // Given the hostname, username and password, another Nigori object capable of // encrypting and decrypting the same data as this one could be initialized. diff --git a/chrome/browser/sync/util/nigori_unittest.cc b/chrome/browser/sync/util/nigori_unittest.cc index ec42911..5626957 100644 --- a/chrome/browser/sync/util/nigori_unittest.cc +++ b/chrome/browser/sync/util/nigori_unittest.cc @@ -10,20 +10,23 @@ #include "base/string_util.h" #include "testing/gtest/include/gtest/gtest.h" +namespace browser_sync { +namespace { + TEST(NigoriTest, Parameters) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); EXPECT_STREQ("example.com", nigori.hostname().c_str()); EXPECT_STREQ("username", nigori.username().c_str()); EXPECT_STREQ("password", nigori.password().c_str()); } TEST(NigoriTest, Permute) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string permuted; - EXPECT_TRUE(nigori.Permute(browser_sync::Nigori::Password, "test name", + EXPECT_TRUE(nigori.Permute(Nigori::Password, "test name", &permuted)); std::string expected = @@ -33,19 +36,19 @@ TEST(NigoriTest, Permute) { } TEST(NigoriTest, PermuteIsConstant) { - browser_sync::Nigori nigori1("example.com"); - EXPECT_TRUE(nigori1.Init("username", "password")); + Nigori nigori1; + EXPECT_TRUE(nigori1.InitByDerivation("example.com", "username", "password")); std::string permuted1; - EXPECT_TRUE(nigori1.Permute(browser_sync::Nigori::Password, + EXPECT_TRUE(nigori1.Permute(Nigori::Password, "name", &permuted1)); - browser_sync::Nigori nigori2("example.com"); - EXPECT_TRUE(nigori2.Init("username", "password")); + Nigori nigori2; + EXPECT_TRUE(nigori2.InitByDerivation("example.com", "username", "password")); std::string permuted2; - EXPECT_TRUE(nigori2.Permute(browser_sync::Nigori::Password, + EXPECT_TRUE(nigori2.Permute(Nigori::Password, "name", &permuted2)); @@ -54,8 +57,8 @@ TEST(NigoriTest, PermuteIsConstant) { } TEST(NigoriTest, EncryptDifferentIv) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string plaintext("value"); @@ -69,8 +72,8 @@ TEST(NigoriTest, EncryptDifferentIv) { } TEST(NigoriTest, Decrypt) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string encrypted = "e7+JyS6ibj6F5qqvpseukNRTZ+oBpu5iuv2VYjOfrH1dNiFLNf7Ov0" @@ -84,8 +87,8 @@ TEST(NigoriTest, Decrypt) { } TEST(NigoriTest, EncryptDecrypt) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string plaintext("value"); @@ -99,8 +102,8 @@ TEST(NigoriTest, EncryptDecrypt) { } TEST(NigoriTest, CorruptedIv) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string plaintext("test"); @@ -117,8 +120,8 @@ TEST(NigoriTest, CorruptedIv) { } TEST(NigoriTest, CorruptedCiphertext) { - browser_sync::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); + Nigori nigori; + EXPECT_TRUE(nigori.InitByDerivation("example.com", "username", "password")); std::string plaintext("test"); @@ -126,11 +129,44 @@ TEST(NigoriTest, CorruptedCiphertext) { EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted)); // Corrput the ciphertext by changing one of its bytes. - encrypted[browser_sync::Nigori::kIvSize + 10] = - (encrypted[browser_sync::Nigori::kIvSize + 10] == 'a' ? 'b' : 'a'); + encrypted[Nigori::kIvSize + 10] = + (encrypted[Nigori::kIvSize + 10] == 'a' ? 'b' : 'a'); std::string decrypted; EXPECT_FALSE(nigori.Decrypt(encrypted, &decrypted)); EXPECT_NE(plaintext, decrypted); } + +TEST(NigoriTest, ExportImport) { + Nigori nigori1; + EXPECT_TRUE(nigori1.InitByDerivation("example.com", "username", "password")); + + std::string user_key; + std::string encryption_key; + std::string mac_key; + EXPECT_TRUE(nigori1.ExportKeys(&user_key, &encryption_key, &mac_key)); + + Nigori nigori2; + EXPECT_TRUE(nigori2.InitByImport(user_key, encryption_key, mac_key)); + + std::string original("test"); + std::string plaintext; + std::string ciphertext; + + EXPECT_TRUE(nigori1.Encrypt(original, &ciphertext)); + EXPECT_TRUE(nigori2.Decrypt(ciphertext, &plaintext)); + EXPECT_EQ(original, plaintext); + + EXPECT_TRUE(nigori2.Encrypt(original, &ciphertext)); + EXPECT_TRUE(nigori1.Decrypt(ciphertext, &plaintext)); + EXPECT_EQ(original, plaintext); + + std::string permuted1, permuted2; + EXPECT_TRUE(nigori1.Permute(Nigori::Password, original, &permuted1)); + EXPECT_TRUE(nigori2.Permute(Nigori::Password, original, &permuted2)); + EXPECT_EQ(permuted1, permuted2); +} + +} // anonymous namespace +} // namespace browser_sync |