diff options
author | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-01 19:05:48 +0000 |
---|---|---|
committer | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-01 19:05:48 +0000 |
commit | b7c6924e54a0e9b1244bb86b0d71e1f677fb9f0e (patch) | |
tree | 6d96e2b94dfe74c50a11c097d56c981e542d2928 /base | |
parent | 9aed77b6dace047bff676a7cdcfef345a858d1a7 (diff) | |
download | chromium_src-b7c6924e54a0e9b1244bb86b0d71e1f677fb9f0e.zip chromium_src-b7c6924e54a0e9b1244bb86b0d71e1f677fb9f0e.tar.gz chromium_src-b7c6924e54a0e9b1244bb86b0d71e1f677fb9f0e.tar.bz2 |
Move the Nigori classes from base to sync.
BUG=none
TEST=NigoriTest
Review URL: http://codereview.chromium.org/1549012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43366 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 1 | ||||
-rw-r--r-- | base/base.gypi | 2 | ||||
-rw-r--r-- | base/nigori.cc | 221 | ||||
-rw-r--r-- | base/nigori.h | 72 | ||||
-rw-r--r-- | base/nigori_unittest.cc | 101 |
5 files changed, 0 insertions, 397 deletions
diff --git a/base/base.gyp b/base/base.gyp index 37c21ff..72255de 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -100,7 +100,6 @@ 'mac_util_unittest.mm', 'message_loop_unittest.cc', 'message_pump_glib_unittest.cc', - 'nigori_unittest.cc', 'object_watcher_unittest.cc', 'observer_list_unittest.cc', 'path_service_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 0e6d6b4..967b3aae 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -535,8 +535,6 @@ 'message_pump_libevent.h', 'message_pump_mac.h', 'message_pump_mac.mm', - 'nigori.h', - 'nigori.cc', 'nsimage_cache_mac.h', 'nsimage_cache_mac.mm', 'nss_util.cc', diff --git a/base/nigori.cc b/base/nigori.cc deleted file mode 100644 index 753417d..0000000 --- a/base/nigori.cc +++ /dev/null @@ -1,221 +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 "base/nigori.h" - -#if defined(OS_WIN) -#include <winsock2.h> // for htonl -#endif - -#include <sstream> -#include <vector> - -#include "base/base64.h" -#include "base/crypto/encryptor.h" -#include "base/hmac.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/string_util.h" - -namespace base { - -// NigoriStream simplifies the concatenation operation of the Nigori protocol. -class NigoriStream { - public: - // Append the big-endian representation of the length of |value| with 32 bits, - // followed by |value| itself to the stream. - NigoriStream& operator<<(const std::string& value) { - uint32 size = htonl(value.size()); - stream_.write((char *) &size, sizeof(uint32)); - stream_ << value; - return *this; - } - - // Append the big-endian representation of the length of |type| with 32 bits, - // followed by the big-endian representation of the value of |type|, with 32 - // bits, to the stream. - NigoriStream& operator<<(const Nigori::Type type) { - uint32 size = htonl(sizeof(uint32)); - stream_.write((char *) &size, sizeof(uint32)); - uint32 value = htonl(type); - stream_.write((char *) &value, sizeof(uint32)); - return *this; - } - - std::string str() { - return stream_.str(); - } - - private: - std::ostringstream stream_; -}; - -// static -const char Nigori::kSaltSalt[] = "saltsalt"; - -Nigori::Nigori(const std::string& hostname) - : hostname_(hostname) { -} - -Nigori::~Nigori() { -} - -bool Nigori::Init(const std::string& username, const std::string& password) { - NigoriStream salt_password; - salt_password << username << hostname_; - - // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8) - scoped_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword( - SymmetricKey::HMAC_SHA1, salt_password.str(), - kSaltSalt, - kSaltIterations, - kSaltKeySize)); - DCHECK(user_salt.get()); - - std::string raw_user_salt; - user_salt->GetRawKey(&raw_user_salt); - - // Kuser = PBKDF2(P, Suser, Nuser, 16) - user_key_.reset(SymmetricKey::DeriveKeyFromPassword(SymmetricKey::AES, - password, raw_user_salt, kUserIterations, kDerivedKeySizeInBits)); - DCHECK(user_key_.get()); - - // Kenc = PBKDF2(P, Suser, Nenc, 16) - encryption_key_.reset(SymmetricKey::DeriveKeyFromPassword(SymmetricKey::AES, - password, raw_user_salt, kEncryptionIterations, kDerivedKeySizeInBits)); - DCHECK(encryption_key_.get()); - - // Kmac = PBKDF2(P, Suser, Nmac, 16) - mac_key_.reset(SymmetricKey::DeriveKeyFromPassword( - SymmetricKey::HMAC_SHA1, password, raw_user_salt, kSigningIterations, - kDerivedKeySizeInBits)); - DCHECK(mac_key_.get()); - - return true; -} - -// Permute[Kenc,Kmac](type || name) -bool Nigori::Permute(Type type, const std::string& name, - std::string* permuted) { - DCHECK_LT(0U, name.size()); - - NigoriStream plaintext; - plaintext << type << name; - - Encryptor encryptor; - if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, - std::string(kIvSize, 0))) - return false; - - std::string ciphertext; - if (!encryptor.Encrypt(plaintext.str(), &ciphertext)) - return false; - - std::string raw_mac_key; - if (!mac_key_->GetRawKey(&raw_mac_key)) - return false; - - HMAC hmac(HMAC::SHA256); - if (!hmac.Init(raw_mac_key)) - return false; - - std::vector<unsigned char> hash(kHashSize); - if (!hmac.Sign(ciphertext, &hash[0], hash.size())) - return false; - - std::string output; - output.assign(ciphertext); - output.append(hash.begin(), hash.end()); - - return Base64Encode(output, permuted); -} - -std::string GenerateRandomString(size_t size) { - // TODO(albertb): Use a secure random function. - std::string random(size, 0); - for (size_t i = 0; i < size; ++i) - random[i] = RandInt(0, 0xff); - return random; -} - -// Enc[Kenc,Kmac](value) -bool Nigori::Encrypt(const std::string& value, std::string* encrypted) { - DCHECK_LT(0U, value.size()); - - std::string iv = GenerateRandomString(kIvSize); - - Encryptor encryptor; - if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv)) - return false; - - std::string ciphertext; - if (!encryptor.Encrypt(value, &ciphertext)) - return false; - - std::string raw_mac_key; - if (!mac_key_->GetRawKey(&raw_mac_key)) - return false; - - HMAC hmac(HMAC::SHA256); - if (!hmac.Init(raw_mac_key)) - return false; - - std::vector<unsigned char> hash(kHashSize); - if (!hmac.Sign(ciphertext, &hash[0], hash.size())) - return false; - - std::string output; - output.assign(iv); - output.append(ciphertext); - output.append(hash.begin(), hash.end()); - - return Base64Encode(output, encrypted); -} - -bool Nigori::Decrypt(const std::string& encrypted, std::string* value) { - std::string input; - if (!Base64Decode(encrypted, &input)) - return false; - - if (input.size() < kIvSize * 2 + kHashSize) - return false; - - // The input is: - // * iv (16 bytes) - // * ciphertext (multiple of 16 bytes) - // * hash (32 bytes) - std::string iv(input.substr(0, kIvSize)); - std::string ciphertext(input.substr(kIvSize, - input.size() - (kIvSize + kHashSize))); - std::string hash(input.substr(input.size() - kHashSize, kHashSize)); - - std::string raw_mac_key; - if (!mac_key_->GetRawKey(&raw_mac_key)) - return false; - - HMAC hmac(HMAC::SHA256); - if (!hmac.Init(raw_mac_key)) - return false; - - std::vector<unsigned char> expected(kHashSize); - if (!hmac.Sign(ciphertext, &expected[0], expected.size())) - return false; - - if (hash.compare(0, hash.size(), - reinterpret_cast<char *>(&expected[0]), - expected.size())) - return false; - - Encryptor encryptor; - if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv)) - return false; - - std::string plaintext; - if (!encryptor.Decrypt(ciphertext, value)) - return false; - - return true; -} - -} // namespace base diff --git a/base/nigori.h b/base/nigori.h deleted file mode 100644 index df6bf9a..0000000 --- a/base/nigori.h +++ /dev/null @@ -1,72 +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 BASE_CRYPTO_NIGORI_H_ -#define BASE_CRYPTO_NIGORI_H_ - -#include <string> - -#include "base/crypto/symmetric_key.h" -#include "base/scoped_ptr.h" - -namespace base { - -// A (partial) implementation of Nigori, a protocol to securely store secrets in -// the cloud. This implementation does not support server authentication or -// assisted key derivation. -// -// To store secrets securely, use the |Permute| method to derive a lookup name -// for your secret (basically a map key), and |Encrypt| and |Decrypt| to store -// and retrieve the secret. -// -// TODO: Link to doc. -class Nigori { - public: - enum Type { - 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); - virtual ~Nigori(); - - // Initialize the client with the supplied |username| and |password|. - bool Init(const std::string& username, const std::string& password); - - // Derives a secure lookup name from |type| and |name|. If |hostname|, - // |username| and |password| are kept constant, a given |type| and |name| pair - // always yields the same |permuted| value. Note that |permuted| will be - // Base64 encoded. - bool Permute(Type type, const std::string& name, std::string* permuted); - - // Encrypts |value|. Note that on success, |encrypted| will be Base64 - // encoded. - bool Encrypt(const std::string& value, std::string* encrypted); - - // Decrypts |value| into |decrypted|. It is assumed that |value| is Base64 - // encoded. - bool Decrypt(const std::string& value, std::string* decrypted); - - static const char kSaltSalt[]; // The salt used to derive the user salt. - static const size_t kSaltKeySize = 8; - static const size_t kDerivedKeySizeInBits = 128; - static const size_t kIvSize = 16; - static const size_t kHashSize = 32; - - static const size_t kSaltIterations = 1001; - static const size_t kUserIterations = 1002; - static const size_t kEncryptionIterations = 1003; - static const size_t kSigningIterations = 1004; - - private: - const std::string hostname_; - scoped_ptr<SymmetricKey> user_key_; - scoped_ptr<SymmetricKey> encryption_key_; - scoped_ptr<SymmetricKey> mac_key_; -}; - -} // namespace base - -#endif // BASE_CRYPTO_NIGORI_H_ diff --git a/base/nigori_unittest.cc b/base/nigori_unittest.cc deleted file mode 100644 index 6ebbd00..0000000 --- a/base/nigori_unittest.cc +++ /dev/null @@ -1,101 +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 "base/nigori.h" - -#include <string> - -#include "base/scoped_ptr.h" -#include "base/string_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(USE_NSS) -#define MAYBE(name) name -#else -#define MAYBE(name) DISABLED_ ## name -#endif - -TEST(NigoriTest, MAYBE(PermuteIsConstant)) { - base::Nigori nigori1("example.com"); - EXPECT_TRUE(nigori1.Init("username", "password")); - - std::string permuted1; - EXPECT_TRUE(nigori1.Permute(base::Nigori::Password, "name", &permuted1)); - - base::Nigori nigori2("example.com"); - EXPECT_TRUE(nigori2.Init("username", "password")); - - std::string permuted2; - EXPECT_TRUE(nigori2.Permute(base::Nigori::Password, "name", &permuted2)); - - EXPECT_LT(0U, permuted1.size()); - EXPECT_EQ(permuted1, permuted2); -} - -TEST(NigoriTest, MAYBE(EncryptDifferentIv)) { - base::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); - - std::string plaintext("value"); - - std::string encrypted1; - EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted1)); - - std::string encrypted2; - EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted2)); - - EXPECT_NE(encrypted1, encrypted2); -} - -TEST(NigoriTest, MAYBE(EncryptDecrypt)) { - base::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); - - std::string plaintext("value"); - - std::string encrypted; - EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted)); - - std::string decrypted; - EXPECT_TRUE(nigori.Decrypt(encrypted, &decrypted)); - - EXPECT_EQ(plaintext, decrypted); -} - -TEST(NigoriTest, MAYBE(CorruptedIv)) { - base::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); - - std::string plaintext("test"); - - std::string encrypted; - EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted)); - - // Corrupt the IV by changing one of its byte. - encrypted[0] = (encrypted[0] == 'a' ? 'b' : 'a'); - - std::string decrypted; - EXPECT_TRUE(nigori.Decrypt(encrypted, &decrypted)); - - EXPECT_NE(plaintext, decrypted); -} - -TEST(NigoriTest, MAYBE(CorruptedCiphertext)) { - base::Nigori nigori("example.com"); - EXPECT_TRUE(nigori.Init("username", "password")); - - std::string plaintext("test"); - - std::string encrypted; - EXPECT_TRUE(nigori.Encrypt(plaintext, &encrypted)); - - // Corrput the ciphertext by changing one of its bytes. - encrypted[base::Nigori::kIvSize + 10] = - (encrypted[base::Nigori::kIvSize + 10] == 'a' ? 'b' : 'a'); - - std::string decrypted; - EXPECT_FALSE(nigori.Decrypt(encrypted, &decrypted)); - - EXPECT_NE(plaintext, decrypted); -} |