summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authoralbertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-04 21:39:27 +0000
committeralbertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-04 21:39:27 +0000
commite344ead6eddc342c1d3b1684db0bc6f45852c85a (patch)
treef0c4bfc98c83f61f447c3d518b2209de0cc009a8 /chrome/browser
parent461f028ab0acdd69a5af64cf45c84e91eb41396c (diff)
downloadchromium_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.cc18
-rw-r--r--chrome/browser/sync/util/nigori.cc38
-rw-r--r--chrome/browser/sync/util/nigori.h21
-rw-r--r--chrome/browser/sync/util/nigori_unittest.cc82
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