| Index: sync/util/nigori.cc
|
| diff --git a/sync/util/nigori.cc b/sync/util/nigori.cc
|
| deleted file mode 100644
|
| index 78ed2876e6537b0d08c8ae797fd2a497d7d370e8..0000000000000000000000000000000000000000
|
| --- a/sync/util/nigori.cc
|
| +++ /dev/null
|
| @@ -1,252 +0,0 @@
|
| -// Copyright (c) 2012 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 "sync/util/nigori.h"
|
| -
|
| -#include <stdint.h>
|
| -
|
| -#include <sstream>
|
| -#include <vector>
|
| -
|
| -#include "base/base64.h"
|
| -#include "base/logging.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/sys_byteorder.h"
|
| -#include "crypto/encryptor.h"
|
| -#include "crypto/hmac.h"
|
| -#include "crypto/random.h"
|
| -#include "crypto/symmetric_key.h"
|
| -
|
| -using base::Base64Encode;
|
| -using base::Base64Decode;
|
| -using crypto::Encryptor;
|
| -using crypto::HMAC;
|
| -using crypto::SymmetricKey;
|
| -
|
| -namespace syncer {
|
| -
|
| -// 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_t size = base::HostToNet32(value.size());
|
| -
|
| - stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
|
| - 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_t size = base::HostToNet32(sizeof(uint32_t));
|
| - stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
|
| - uint32_t value = base::HostToNet32(type);
|
| - stream_.write(reinterpret_cast<char*>(&value), sizeof(uint32_t));
|
| - return *this;
|
| - }
|
| -
|
| - std::string str() {
|
| - return stream_.str();
|
| - }
|
| -
|
| - private:
|
| - std::ostringstream stream_;
|
| -};
|
| -
|
| -// static
|
| -const char Nigori::kSaltSalt[] = "saltsalt";
|
| -
|
| -Nigori::Nigori() {
|
| -}
|
| -
|
| -Nigori::~Nigori() {
|
| -}
|
| -
|
| -bool Nigori::InitByDerivation(const std::string& hostname,
|
| - const std::string& username,
|
| - const std::string& password) {
|
| - NigoriStream salt_password;
|
| - salt_password << username << hostname;
|
| -
|
| - // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8)
|
| - std::unique_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword(
|
| - SymmetricKey::HMAC_SHA1, salt_password.str(), kSaltSalt, kSaltIterations,
|
| - kSaltKeySizeInBits));
|
| - DCHECK(user_salt);
|
| -
|
| - std::string raw_user_salt;
|
| - if (!user_salt->GetRawKey(&raw_user_salt))
|
| - return false;
|
| -
|
| - // Kuser = PBKDF2(P, Suser, Nuser, 16)
|
| - user_key_ = SymmetricKey::DeriveKeyFromPassword(
|
| - SymmetricKey::AES, password, raw_user_salt, kUserIterations,
|
| - kDerivedKeySizeInBits);
|
| - DCHECK(user_key_);
|
| -
|
| - // Kenc = PBKDF2(P, Suser, Nenc, 16)
|
| - encryption_key_ = SymmetricKey::DeriveKeyFromPassword(
|
| - SymmetricKey::AES, password, raw_user_salt, kEncryptionIterations,
|
| - kDerivedKeySizeInBits);
|
| - DCHECK(encryption_key_);
|
| -
|
| - // Kmac = PBKDF2(P, Suser, Nmac, 16)
|
| - mac_key_ = SymmetricKey::DeriveKeyFromPassword(
|
| - SymmetricKey::HMAC_SHA1, password, raw_user_salt, kSigningIterations,
|
| - kDerivedKeySizeInBits);
|
| - DCHECK(mac_key_);
|
| -
|
| - return user_key_ && encryption_key_ && mac_key_;
|
| -}
|
| -
|
| -bool Nigori::InitByImport(const std::string& user_key,
|
| - const std::string& encryption_key,
|
| - const std::string& mac_key) {
|
| - user_key_ = SymmetricKey::Import(SymmetricKey::AES, user_key);
|
| - DCHECK(user_key_);
|
| -
|
| - encryption_key_ = SymmetricKey::Import(SymmetricKey::AES, encryption_key);
|
| - DCHECK(encryption_key_);
|
| -
|
| - mac_key_ = SymmetricKey::Import(SymmetricKey::HMAC_SHA1, mac_key);
|
| - DCHECK(mac_key_);
|
| -
|
| - return user_key_ && encryption_key_ && mac_key_;
|
| -}
|
| -
|
| -// Permute[Kenc,Kmac](type || name)
|
| -bool Nigori::Permute(Type type, const std::string& name,
|
| - std::string* permuted) const {
|
| - 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());
|
| -
|
| - Base64Encode(output, permuted);
|
| - return true;
|
| -}
|
| -
|
| -// Enc[Kenc,Kmac](value)
|
| -bool Nigori::Encrypt(const std::string& value, std::string* encrypted) const {
|
| - if (0U >= value.size())
|
| - return false;
|
| -
|
| - std::string iv;
|
| - crypto::RandBytes(base::WriteInto(&iv, kIvSize + 1), 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());
|
| -
|
| - Base64Encode(output, encrypted);
|
| - return true;
|
| -}
|
| -
|
| -bool Nigori::Decrypt(const std::string& encrypted, std::string* value) const {
|
| - 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;
|
| -
|
| - if (!encryptor.Decrypt(ciphertext, value))
|
| - return false;
|
| -
|
| - 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 syncer
|
|
|