Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: sync/util/nigori.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sync/util/nigori.h ('k') | sync/util/nigori_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sync/util/nigori.h"
6
7 #include <stdint.h>
8
9 #include <sstream>
10 #include <vector>
11
12 #include "base/base64.h"
13 #include "base/logging.h"
14 #include "base/strings/string_util.h"
15 #include "base/sys_byteorder.h"
16 #include "crypto/encryptor.h"
17 #include "crypto/hmac.h"
18 #include "crypto/random.h"
19 #include "crypto/symmetric_key.h"
20
21 using base::Base64Encode;
22 using base::Base64Decode;
23 using crypto::Encryptor;
24 using crypto::HMAC;
25 using crypto::SymmetricKey;
26
27 namespace syncer {
28
29 // NigoriStream simplifies the concatenation operation of the Nigori protocol.
30 class NigoriStream {
31 public:
32 // Append the big-endian representation of the length of |value| with 32 bits,
33 // followed by |value| itself to the stream.
34 NigoriStream& operator<<(const std::string& value) {
35 uint32_t size = base::HostToNet32(value.size());
36
37 stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
38 stream_ << value;
39 return *this;
40 }
41
42 // Append the big-endian representation of the length of |type| with 32 bits,
43 // followed by the big-endian representation of the value of |type|, with 32
44 // bits, to the stream.
45 NigoriStream& operator<<(const Nigori::Type type) {
46 uint32_t size = base::HostToNet32(sizeof(uint32_t));
47 stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
48 uint32_t value = base::HostToNet32(type);
49 stream_.write(reinterpret_cast<char*>(&value), sizeof(uint32_t));
50 return *this;
51 }
52
53 std::string str() {
54 return stream_.str();
55 }
56
57 private:
58 std::ostringstream stream_;
59 };
60
61 // static
62 const char Nigori::kSaltSalt[] = "saltsalt";
63
64 Nigori::Nigori() {
65 }
66
67 Nigori::~Nigori() {
68 }
69
70 bool Nigori::InitByDerivation(const std::string& hostname,
71 const std::string& username,
72 const std::string& password) {
73 NigoriStream salt_password;
74 salt_password << username << hostname;
75
76 // Suser = PBKDF2(Username || Servername, "saltsalt", Nsalt, 8)
77 std::unique_ptr<SymmetricKey> user_salt(SymmetricKey::DeriveKeyFromPassword(
78 SymmetricKey::HMAC_SHA1, salt_password.str(), kSaltSalt, kSaltIterations,
79 kSaltKeySizeInBits));
80 DCHECK(user_salt);
81
82 std::string raw_user_salt;
83 if (!user_salt->GetRawKey(&raw_user_salt))
84 return false;
85
86 // Kuser = PBKDF2(P, Suser, Nuser, 16)
87 user_key_ = SymmetricKey::DeriveKeyFromPassword(
88 SymmetricKey::AES, password, raw_user_salt, kUserIterations,
89 kDerivedKeySizeInBits);
90 DCHECK(user_key_);
91
92 // Kenc = PBKDF2(P, Suser, Nenc, 16)
93 encryption_key_ = SymmetricKey::DeriveKeyFromPassword(
94 SymmetricKey::AES, password, raw_user_salt, kEncryptionIterations,
95 kDerivedKeySizeInBits);
96 DCHECK(encryption_key_);
97
98 // Kmac = PBKDF2(P, Suser, Nmac, 16)
99 mac_key_ = SymmetricKey::DeriveKeyFromPassword(
100 SymmetricKey::HMAC_SHA1, password, raw_user_salt, kSigningIterations,
101 kDerivedKeySizeInBits);
102 DCHECK(mac_key_);
103
104 return user_key_ && encryption_key_ && mac_key_;
105 }
106
107 bool Nigori::InitByImport(const std::string& user_key,
108 const std::string& encryption_key,
109 const std::string& mac_key) {
110 user_key_ = SymmetricKey::Import(SymmetricKey::AES, user_key);
111 DCHECK(user_key_);
112
113 encryption_key_ = SymmetricKey::Import(SymmetricKey::AES, encryption_key);
114 DCHECK(encryption_key_);
115
116 mac_key_ = SymmetricKey::Import(SymmetricKey::HMAC_SHA1, mac_key);
117 DCHECK(mac_key_);
118
119 return user_key_ && encryption_key_ && mac_key_;
120 }
121
122 // Permute[Kenc,Kmac](type || name)
123 bool Nigori::Permute(Type type, const std::string& name,
124 std::string* permuted) const {
125 DCHECK_LT(0U, name.size());
126
127 NigoriStream plaintext;
128 plaintext << type << name;
129
130 Encryptor encryptor;
131 if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC,
132 std::string(kIvSize, 0)))
133 return false;
134
135 std::string ciphertext;
136 if (!encryptor.Encrypt(plaintext.str(), &ciphertext))
137 return false;
138
139 std::string raw_mac_key;
140 if (!mac_key_->GetRawKey(&raw_mac_key))
141 return false;
142
143 HMAC hmac(HMAC::SHA256);
144 if (!hmac.Init(raw_mac_key))
145 return false;
146
147 std::vector<unsigned char> hash(kHashSize);
148 if (!hmac.Sign(ciphertext, &hash[0], hash.size()))
149 return false;
150
151 std::string output;
152 output.assign(ciphertext);
153 output.append(hash.begin(), hash.end());
154
155 Base64Encode(output, permuted);
156 return true;
157 }
158
159 // Enc[Kenc,Kmac](value)
160 bool Nigori::Encrypt(const std::string& value, std::string* encrypted) const {
161 if (0U >= value.size())
162 return false;
163
164 std::string iv;
165 crypto::RandBytes(base::WriteInto(&iv, kIvSize + 1), kIvSize);
166
167 Encryptor encryptor;
168 if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv))
169 return false;
170
171 std::string ciphertext;
172 if (!encryptor.Encrypt(value, &ciphertext))
173 return false;
174
175 std::string raw_mac_key;
176 if (!mac_key_->GetRawKey(&raw_mac_key))
177 return false;
178
179 HMAC hmac(HMAC::SHA256);
180 if (!hmac.Init(raw_mac_key))
181 return false;
182
183 std::vector<unsigned char> hash(kHashSize);
184 if (!hmac.Sign(ciphertext, &hash[0], hash.size()))
185 return false;
186
187 std::string output;
188 output.assign(iv);
189 output.append(ciphertext);
190 output.append(hash.begin(), hash.end());
191
192 Base64Encode(output, encrypted);
193 return true;
194 }
195
196 bool Nigori::Decrypt(const std::string& encrypted, std::string* value) const {
197 std::string input;
198 if (!Base64Decode(encrypted, &input))
199 return false;
200
201 if (input.size() < kIvSize * 2 + kHashSize)
202 return false;
203
204 // The input is:
205 // * iv (16 bytes)
206 // * ciphertext (multiple of 16 bytes)
207 // * hash (32 bytes)
208 std::string iv(input.substr(0, kIvSize));
209 std::string ciphertext(input.substr(kIvSize,
210 input.size() - (kIvSize + kHashSize)));
211 std::string hash(input.substr(input.size() - kHashSize, kHashSize));
212
213 std::string raw_mac_key;
214 if (!mac_key_->GetRawKey(&raw_mac_key))
215 return false;
216
217 HMAC hmac(HMAC::SHA256);
218 if (!hmac.Init(raw_mac_key))
219 return false;
220
221 std::vector<unsigned char> expected(kHashSize);
222 if (!hmac.Sign(ciphertext, &expected[0], expected.size()))
223 return false;
224
225 if (hash.compare(0, hash.size(),
226 reinterpret_cast<char *>(&expected[0]),
227 expected.size()))
228 return false;
229
230 Encryptor encryptor;
231 if (!encryptor.Init(encryption_key_.get(), Encryptor::CBC, iv))
232 return false;
233
234 if (!encryptor.Decrypt(ciphertext, value))
235 return false;
236
237 return true;
238 }
239
240 bool Nigori::ExportKeys(std::string* user_key,
241 std::string* encryption_key,
242 std::string* mac_key) const {
243 DCHECK(user_key);
244 DCHECK(encryption_key);
245 DCHECK(mac_key);
246
247 return user_key_->GetRawKey(user_key) &&
248 encryption_key_->GetRawKey(encryption_key) &&
249 mac_key_->GetRawKey(mac_key);
250 }
251
252 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/util/nigori.h ('k') | sync/util/nigori_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698