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

Side by Side Diff: components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc

Issue 2713673002: Separate out the scheme from the GCMMessageCryptographer (Closed)
Patch Set: Separate out the scheme from the GCMMessageCryptographer Created 3 years, 10 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h" 5 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
6 6
7 #include <stddef.h>
8
9 #include <memory> 7 #include <memory>
10 8
11 #include "base/base64url.h" 9 #include "base/base64url.h"
12 #include "base/macros.h" 10 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
14 #include "components/gcm_driver/crypto/p256_key_util.h" 12 #include "components/gcm_driver/crypto/p256_key_util.h"
15 #include "crypto/random.h" 13 #include "crypto/random.h"
16 #include "crypto/symmetric_key.h" 14 #include "crypto/symmetric_key.h"
17 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
18 16
19 namespace gcm { 17 namespace gcm {
20 18
21 namespace { 19 namespace {
22 20
21 // Example plaintext data to use in the tests.
22 const char kExamplePlaintext[] = "Example plaintext";
23
23 // The number of bits of the key in AEAD_AES_128_GCM. 24 // The number of bits of the key in AEAD_AES_128_GCM.
24 const size_t kKeySizeBits = 128; 25 const size_t kKeySizeBits = 128;
25 26
26 // Example plaintext data to use in the tests. 27 // Public keys of both the sender and the recipient as base64url-encoded
27 const char kExamplePlaintext[] = "Example plaintext"; 28 // uncompressed P-256 EC points, as well as an authentication secret used for
28 29 // the reference vectors. All used to create stable output.
29 // Fixed local and peer public keys must be used to get consistent results. 30 const char kCommonRecipientPublicKey[] =
30 const char kLocalPublicKeyCommon[] =
31 "BIXzEKOFquzVlr_1tS1bhmobZU3IJq2bswDflMJsizixqd_HFSvCJaCAotNjBw6A-iKQk7FshA" 31 "BIXzEKOFquzVlr_1tS1bhmobZU3IJq2bswDflMJsizixqd_HFSvCJaCAotNjBw6A-iKQk7FshA"
32 "jdAA-T9Rh1a7U"; 32 "jdAA-T9Rh1a7U";
33 33 const char kCommonSenderPublicKey[] =
34 const char kPeerPublicKeyCommon[] =
35 "BAuzSrdIyKZsHnuOhqklkIKi6fl65V9OdPy6nFwI2SywL5-6I5SkkDtfIL9y7NkoEE345jv2Eo" 34 "BAuzSrdIyKZsHnuOhqklkIKi6fl65V9OdPy6nFwI2SywL5-6I5SkkDtfIL9y7NkoEE345jv2Eo"
36 "5n4NIbLJIBjTM"; 35 "5n4NIbLJIBjTM";
36 const char kCommonAuthSecret[] = "MyAuthenticationSecret";
37 37
38 const char kAuthSecretCommon[] = "MyAuthenticationSecret"; 38 // Test vectors containing reference input for draft-ietf-webpush-encryption-03
39 39 // that was created using an separate JavaScript implementation of the draft.
40 // A test vector contains the information necessary to either encrypt or decrypt
41 // a message. These vectors were created using a JavaScript implementation of
42 // the same RFCs that the GCMMessageCryptographer implements.
43 struct TestVector { 40 struct TestVector {
44 const char* const input; 41 const char* const input;
45 const char* const key; 42 const char* const ecdh_shared_secret;
46 const char* const salt; 43 const char* const salt;
47 size_t record_size; 44 size_t record_size;
48 const char* const output; 45 const char* const output;
49 }; 46 };
50 47
51 const TestVector kEncryptionTestVectors[] = { 48 const TestVector kEncryptionTestVectorsDraft03[] = {
52 // Simple message. 49 // Simple message.
53 { "Hello, world!", 50 {"Hello, world!", "AhA6n2oFYPWIh-cXwyv1m2C0JvmjHB4ZkXj8QylESXU",
54 "AhA6n2oFYPWIh-cXwyv1m2C0JvmjHB4ZkXj8QylESXU", 51 "tsJYqAGvFDk6lDEv7daecw", 4096,
55 "tsJYqAGvFDk6lDEv7daecw", 52 "FgWrrnZq79oI_N4ORkVLHx1jfVmjeiIk-xFX8PzVuA"},
56 4096, 53 // Empty message.
57 "FgWrrnZq79oI_N4ORkVLHx1jfVmjeiIk-xFX8PzVuA" 54 {"", "lMyvTong4VR053jfCpWmMDGW5dEDAqiTZUIU-inhTjU",
58 }, 55 "wH3uvZqcN6oey9whiGpn1A", 4096, "MTI9zZ8CJTUzbZ4qNDoQZs0k"},
59 // Empty message. 56 // Message with an invalid salt size.
60 { "", 57 {
61 "lMyvTong4VR053jfCpWmMDGW5dEDAqiTZUIU-inhTjU", 58 "Hello, world!", "CcdxzkR6z1EY9vSrM7_IxYVxDxu46hV638EZQTPd7XI",
62 "wH3uvZqcN6oey9whiGpn1A", 59 "aRr1fI1YSGVi5XU", 4096,
63 4096, 60 nullptr // expected to fail
64 "MTI9zZ8CJTUzbZ4qNDoQZs0k" 61 }};
65 },
66 // Message with an invalid salt size.
67 { "Hello, world!",
68 "CcdxzkR6z1EY9vSrM7_IxYVxDxu46hV638EZQTPd7XI",
69 "aRr1fI1YSGVi5XU",
70 4096,
71 nullptr // expected to fail
72 }
73 };
74 62
75 const TestVector kDecryptionTestVectors[] = { 63 const TestVector kDecryptionTestVectorsDraft03[] = {
76 // Simple message. 64 // Simple message.
77 { "ceiEu_YpmqLoakD4smdzvy2XKRQrJ9vBzB2aqYEfzw", 65 {"ceiEu_YpmqLoakD4smdzvy2XKRQrJ9vBzB2aqYEfzw",
78 "47ZytAw9qHlm-Q8g-7rH81rUPzaCgGcoFvlS1qxQtQk", 66 "47ZytAw9qHlm-Q8g-7rH81rUPzaCgGcoFvlS1qxQtQk", "EuR7EVetcaWpndXd_dKeyA",
79 "EuR7EVetcaWpndXd_dKeyA", 67 4096, "Hello, world!"},
80 4096, 68 // Simple message with 16 bytes of padding.
81 "Hello, world!" 69 {"WSf6fz1O0aIJyaPTCnvk83OqIQxsRKeFOvblPLsPpFB_1AV9ROk09TE1cGrB6zQ",
82 }, 70 "MYSsNybwrTzRIzQYUq_yFPc6ugcTrJdEZJDM4NswvUg", "8sEAMQYnufo2UkKl80cUGQ",
83 // Simple message with 16 bytes of padding. 71 4096, "Hello, world!"},
84 { "WSf6fz1O0aIJyaPTCnvk83OqIQxsRKeFOvblPLsPpFB_1AV9ROk09TE1cGrB6zQ", 72 // Empty message.
85 "MYSsNybwrTzRIzQYUq_yFPc6ugcTrJdEZJDM4NswvUg", 73 {"Ur3vHedGDO5IPYDvbhHYjbjG", "S3-Ki_-XtzR66gUp_zR75CC5JXO62pyr5fWfneTYwFE",
86 "8sEAMQYnufo2UkKl80cUGQ", 74 "4RM6s19jJHdmqiVEJDp9jg", 4096, ""},
87 4096, 75 // Message with an invalid salt size.
88 "Hello, world!" 76 {
89 }, 77 "iGrOpmJC5XTTf7wtgdhZ_qT",
90 // Empty message. 78 "wW3Iy5ma803lLd-ysPdHUe2NB3HqXbY0XhCCdG5Y1Gw", "N7oMH_xohAhMhOY", 4096,
91 { "Ur3vHedGDO5IPYDvbhHYjbjG", 79 nullptr // expected to fail
92 "S3-Ki_-XtzR66gUp_zR75CC5JXO62pyr5fWfneTYwFE", 80 },
93 "4RM6s19jJHdmqiVEJDp9jg", 81 // Message with an invalid record size.
94 4096, 82 {
95 "" 83 "iGrOpmJC5XTTf7wtgdhZ_qT",
96 }, 84 "kR5BMfqMKOD1yrLKE2giObXHI7merrMtnoO2oqneqXA", "SQeJSPrqHvTdSfAMF8bBzQ",
97 // Message with an invalid salt size. 85 8,
98 { "iGrOpmJC5XTTf7wtgdhZ_qT", 86 nullptr // expected to fail
99 "wW3Iy5ma803lLd-ysPdHUe2NB3HqXbY0XhCCdG5Y1Gw", 87 },
100 "N7oMH_xohAhMhOY", 88 // Message with multiple (2) records.
101 4096, 89 {
102 nullptr // expected to fail 90 "RqQVHRXlfYjzW9xhzh3V_KijLKjZiKzGXosqN_"
103 }, 91 "IaMzi0zI0tXXhC1urtrk3iWRoqttNXpkD2r"
104 // Message with an invalid record size. 92 "UCgLy8A1FnTjw",
105 { "iGrOpmJC5XTTf7wtgdhZ_qT", 93 "W3W4gx7sqcfmBnvNNdO9d4MBCC1bvJkvsNjZOGD-CCg", "xG0TPGi9aIcxjpXKmaYBBQ",
106 "kR5BMfqMKOD1yrLKE2giObXHI7merrMtnoO2oqneqXA", 94 7,
107 "SQeJSPrqHvTdSfAMF8bBzQ", 95 nullptr // expected to fail
108 8, 96 }};
109 nullptr // expected to fail
110 },
111 // Message with multiple (2) records.
112 { "RqQVHRXlfYjzW9xhzh3V_KijLKjZiKzGXosqN_IaMzi0zI0tXXhC1urtrk3iWRoqttNXpkD2r"
113 "UCgLy8A1FnTjw",
114 "W3W4gx7sqcfmBnvNNdO9d4MBCC1bvJkvsNjZOGD-CCg",
115 "xG0TPGi9aIcxjpXKmaYBBQ",
116 7,
117 nullptr // expected to fail
118 }
119 };
120 97
121 } // namespace 98 } // namespace
122 99
123 class GCMMessageCryptographerTest : public ::testing::Test { 100 class GCMMessageCryptographerTest : public ::testing::Test {
124 public: 101 public:
125 void SetUp() override { 102 void SetUp() override {
103 cryptographer_ = base::MakeUnique<GCMMessageCryptographer>(
104 GCMMessageCryptographer::Version::DRAFT_03);
105
106 ASSERT_TRUE(base::Base64UrlDecode(
107 kCommonRecipientPublicKey, base::Base64UrlDecodePolicy::IGNORE_PADDING,
108 &recipient_public_key_));
109 ASSERT_TRUE(base::Base64UrlDecode(
110 kCommonSenderPublicKey, base::Base64UrlDecodePolicy::IGNORE_PADDING,
111 &sender_public_key_));
112
126 std::unique_ptr<crypto::SymmetricKey> random_key( 113 std::unique_ptr<crypto::SymmetricKey> random_key(
127 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 114 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES,
128 kKeySizeBits)); 115 kKeySizeBits));
129 116
130 ASSERT_TRUE(random_key->GetRawKey(&key_)); 117 ASSERT_TRUE(random_key->GetRawKey(&ecdh_shared_secret_));
131
132 std::string local_public_key, peer_public_key;
133 ASSERT_TRUE(base::Base64UrlDecode(
134 kLocalPublicKeyCommon, base::Base64UrlDecodePolicy::IGNORE_PADDING,
135 &local_public_key));
136 ASSERT_TRUE(base::Base64UrlDecode(
137 kPeerPublicKeyCommon, base::Base64UrlDecodePolicy::IGNORE_PADDING,
138 &peer_public_key));
139
140 cryptographer_.reset(
141 new GCMMessageCryptographer(local_public_key, peer_public_key,
142 kAuthSecretCommon));
143 } 118 }
144 119
145 protected: 120 protected:
146 // Generates a cryptographically secure random salt of 16-octets in size, the 121 // Generates a cryptographically secure random salt of 16-octets in size, the
147 // required length as expected by the HKDF. 122 // required length as expected by the HKDF.
148 std::string GenerateRandomSalt() { 123 std::string GenerateRandomSalt() {
149 const size_t kSaltSize = 16; 124 const size_t kSaltSize = 16;
150 125
151 std::string salt; 126 std::string salt;
152 127
153 crypto::RandBytes(base::WriteInto(&salt, kSaltSize + 1), kSaltSize); 128 crypto::RandBytes(base::WriteInto(&salt, kSaltSize + 1), kSaltSize);
154 return salt; 129 return salt;
155 } 130 }
156 131
157 GCMMessageCryptographer* cryptographer() { return cryptographer_.get(); } 132 // Public keys of the recipient and sender as uncompressed P-256 EC points.
133 std::string recipient_public_key_;
134 std::string sender_public_key_;
158 135
159 base::StringPiece key() const { return key_; } 136 // Shared secret to use in transformations. Unrelated to the keys above.
137 std::string ecdh_shared_secret_;
160 138
161 private: 139 // The GCMMessageCryptographer instance to use for the tests.
162 std::unique_ptr<GCMMessageCryptographer> cryptographer_; 140 std::unique_ptr<GCMMessageCryptographer> cryptographer_;
163
164 std::string key_;
165 }; 141 };
166 142
167 TEST_F(GCMMessageCryptographerTest, RoundTrip) { 143 TEST_F(GCMMessageCryptographerTest, RoundTrip) {
168 const std::string salt = GenerateRandomSalt(); 144 const std::string salt = GenerateRandomSalt();
169 145
170 size_t record_size = 0; 146 size_t record_size = 0;
171 147
172 std::string ciphertext, plaintext; 148 std::string ciphertext, plaintext;
173 ASSERT_TRUE(cryptographer()->Encrypt(kExamplePlaintext, key(), salt, 149 ASSERT_TRUE(cryptographer_->Encrypt(
174 &record_size, &ciphertext)); 150 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
151 kCommonAuthSecret, salt, kExamplePlaintext, &record_size, &ciphertext));
175 152
176 EXPECT_GT(record_size, ciphertext.size() - 16); 153 EXPECT_GT(record_size, ciphertext.size() - 16);
177 EXPECT_GT(ciphertext.size(), 0u); 154 EXPECT_GT(ciphertext.size(), 0u);
178 155
179 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 156 ASSERT_TRUE(cryptographer_->Decrypt(
180 &plaintext)); 157 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
158 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
181 159
182 EXPECT_EQ(kExamplePlaintext, plaintext); 160 EXPECT_EQ(kExamplePlaintext, plaintext);
183 } 161 }
184 162
185 TEST_F(GCMMessageCryptographerTest, RoundTripEmptyMessage) { 163 TEST_F(GCMMessageCryptographerTest, RoundTripEmptyMessage) {
186 const std::string salt = GenerateRandomSalt(); 164 const std::string salt = GenerateRandomSalt();
187 const std::string message = ""; 165 const std::string message = "";
188 166
189 size_t record_size = 0; 167 size_t record_size = 0;
190 168
191 std::string ciphertext, plaintext; 169 std::string ciphertext, plaintext;
192 ASSERT_TRUE(cryptographer()->Encrypt(message, key(), salt, &record_size, 170 ASSERT_TRUE(cryptographer_->Encrypt(
193 &ciphertext)); 171 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
172 kCommonAuthSecret, salt, message, &record_size, &ciphertext));
194 173
195 EXPECT_GT(record_size, ciphertext.size() - 16); 174 EXPECT_GT(record_size, ciphertext.size() - 16);
196 EXPECT_GT(ciphertext.size(), 0u); 175 EXPECT_GT(ciphertext.size(), 0u);
197 176
198 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 177 ASSERT_TRUE(cryptographer_->Decrypt(
199 &plaintext)); 178 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
179 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
200 180
201 EXPECT_EQ(message, plaintext); 181 EXPECT_EQ(message, plaintext);
202 } 182 }
203 183
204 TEST_F(GCMMessageCryptographerTest, InvalidRecordSize) { 184 TEST_F(GCMMessageCryptographerTest, InvalidRecordSize) {
205 const std::string salt = GenerateRandomSalt(); 185 const std::string salt = GenerateRandomSalt();
206 186
207 size_t record_size = 0; 187 size_t record_size = 0;
208 188
209 std::string ciphertext, plaintext; 189 std::string ciphertext, plaintext;
210 ASSERT_TRUE(cryptographer()->Encrypt(kExamplePlaintext, key(), salt, 190 ASSERT_TRUE(cryptographer_->Encrypt(
211 &record_size, &ciphertext)); 191 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
192 kCommonAuthSecret, salt, kExamplePlaintext, &record_size, &ciphertext));
212 193
213 EXPECT_GT(record_size, ciphertext.size() - 16); 194 EXPECT_GT(record_size, ciphertext.size() - 16);
214 EXPECT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt,
215 0 /* record_size */, &plaintext));
216 195
217 EXPECT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, 196 EXPECT_FALSE(cryptographer_->Decrypt(
218 ciphertext.size() - 17, &plaintext)); 197 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
198 kCommonAuthSecret, salt, ciphertext, 0 /* record_size */, &plaintext));
219 199
220 EXPECT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, 200 EXPECT_FALSE(cryptographer_->Decrypt(
221 ciphertext.size() - 16, &plaintext)); 201 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
202 kCommonAuthSecret, salt, ciphertext, ciphertext.size() - 17, &plaintext));
203
204 EXPECT_TRUE(cryptographer_->Decrypt(
205 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
206 kCommonAuthSecret, salt, ciphertext, ciphertext.size() - 16, &plaintext));
222 } 207 }
223 208
224 TEST_F(GCMMessageCryptographerTest, InvalidRecordPadding) { 209 TEST_F(GCMMessageCryptographerTest, InvalidRecordPadding) {
225 std::string message = std::string(sizeof(uint16_t), '\0') + kExamplePlaintext; 210 std::string message = std::string(sizeof(uint16_t), '\0') + kExamplePlaintext;
226 211
227 const std::string salt = GenerateRandomSalt(); 212 const std::string salt = GenerateRandomSalt();
228 213
229 const std::string prk = cryptographer()->DerivePseudoRandomKey(key()); 214 const std::string prk =
230 const std::string nonce = cryptographer()->DeriveNonce(prk, salt); 215 cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
216 ecdh_shared_secret_, kCommonAuthSecret);
231 const std::string content_encryption_key = 217 const std::string content_encryption_key =
232 cryptographer()->DeriveContentEncryptionKey(prk, salt); 218 cryptographer_->DeriveContentEncryptionKey(recipient_public_key_,
219 sender_public_key_, prk, salt);
220 const std::string nonce = cryptographer_->DeriveNonce(
221 recipient_public_key_, sender_public_key_, prk, salt);
233 222
234 ASSERT_GT(message.size(), 1u); 223 ASSERT_GT(message.size(), 1u);
235 const size_t record_size = message.size() + 1; 224 const size_t record_size = message.size() + 1;
236 225
237 std::string ciphertext, plaintext; 226 std::string ciphertext, plaintext;
238 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal( 227 ASSERT_TRUE(cryptographer_->TransformRecord(
239 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce, 228 GCMMessageCryptographer::Direction::ENCRYPT, message,
240 &ciphertext)); 229 content_encryption_key, nonce, &ciphertext));
241 230
242 ASSERT_TRUE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 231 ASSERT_TRUE(cryptographer_->Decrypt(
243 &plaintext)); 232 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
233 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
244 234
245 // Note that GCMMessageCryptographer::Decrypt removes the padding. 235 // Note that GCMMessageCryptographer::Decrypt removes the padding.
246 EXPECT_EQ(kExamplePlaintext, plaintext); 236 EXPECT_EQ(kExamplePlaintext, plaintext);
247 237
248 // Now run the same steps again, but say that there are four padding octets. 238 // Now run the same steps again, but say that there are four padding octets.
249 // This should be rejected because the padding will not be all zeros. 239 // This should be rejected because the padding will not be all zeros.
250 message[0] = 4; 240 message[0] = 4;
251 241
252 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal( 242 ASSERT_TRUE(cryptographer_->TransformRecord(
253 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce, 243 GCMMessageCryptographer::Direction::ENCRYPT, message,
254 &ciphertext)); 244 content_encryption_key, nonce, &ciphertext));
255 245
256 ASSERT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 246 ASSERT_FALSE(cryptographer_->Decrypt(
257 &plaintext)); 247 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
248 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
258 249
259 // Do the same but changing the second octet indicating padding size, leaving 250 // Do the same but changing the second octet indicating padding size, leaving
260 // the first octet at zero. 251 // the first octet at zero.
261 message[0] = 0; 252 message[0] = 0;
262 message[1] = 4; 253 message[1] = 4;
263 254
264 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal( 255 ASSERT_TRUE(cryptographer_->TransformRecord(
265 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce, 256 GCMMessageCryptographer::Direction::ENCRYPT, message,
266 &ciphertext)); 257 content_encryption_key, nonce, &ciphertext));
267 258
268 ASSERT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 259 ASSERT_FALSE(cryptographer_->Decrypt(
269 &plaintext)); 260 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
261 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
270 262
271 // Run the same steps again, but say that there are more padding octets than 263 // Run the same steps again, but say that there are more padding octets than
272 // the length of the message. 264 // the length of the message.
273 message[0] = 64; 265 message[0] = 64;
274 266
275 EXPECT_GT(static_cast<size_t>(message[0]), message.size()); 267 EXPECT_GT(static_cast<size_t>(message[0]), message.size());
276 ASSERT_TRUE(cryptographer()->EncryptDecryptRecordInternal( 268 ASSERT_TRUE(cryptographer_->TransformRecord(
277 GCMMessageCryptographer::ENCRYPT, message, content_encryption_key, nonce, 269 GCMMessageCryptographer::Direction::ENCRYPT, message,
278 &ciphertext)); 270 content_encryption_key, nonce, &ciphertext));
279 271
280 ASSERT_FALSE(cryptographer()->Decrypt(ciphertext, key(), salt, record_size, 272 ASSERT_FALSE(cryptographer_->Decrypt(
281 &plaintext)); 273 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
274 kCommonAuthSecret, salt, ciphertext, record_size, &plaintext));
282 } 275 }
283 276
284 TEST_F(GCMMessageCryptographerTest, EncryptionTestVectors) { 277 TEST_F(GCMMessageCryptographerTest, AuthSecretAffectsPRK) {
285 std::string key, salt, output, ciphertext; 278 ASSERT_NE(cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
279 ecdh_shared_secret_, "Hello"),
280 cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
281 ecdh_shared_secret_, "World"));
282
283 std::string salt = GenerateRandomSalt();
284
285 // Verify that the IKM actually gets used by the transformations.
286 size_t hello_record_size, world_record_size;
287 std::string hello_ciphertext, world_ciphertext;
288
289 ASSERT_TRUE(cryptographer_->Encrypt(
290 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, "Hello",
291 salt, kExamplePlaintext, &hello_record_size, &hello_ciphertext));
292
293 ASSERT_TRUE(cryptographer_->Encrypt(
294 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, "World",
295 salt, kExamplePlaintext, &world_record_size, &world_ciphertext));
296
297 // If the ciphertexts differ despite the same key and salt, it got used.
298 ASSERT_NE(hello_ciphertext, world_ciphertext);
299 EXPECT_EQ(hello_record_size, world_record_size);
300
301 // Verify that the different ciphertexts can also be translated back to the
302 // plaintext content. This will fail if the auth secret isn't considered.
303 std::string hello_plaintext, world_plaintext;
304
305 ASSERT_TRUE(cryptographer_->Decrypt(
306 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, "Hello",
307 salt, hello_ciphertext, hello_record_size, &hello_plaintext));
308
309 ASSERT_TRUE(cryptographer_->Decrypt(
310 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, "World",
311 salt, world_ciphertext, world_record_size, &world_plaintext));
312
313 EXPECT_EQ(kExamplePlaintext, hello_plaintext);
314 EXPECT_EQ(kExamplePlaintext, world_plaintext);
315 }
316
317 class GCMMessageCryptographerTestVectorTest
318 : public GCMMessageCryptographerTest {};
319
320 TEST_F(GCMMessageCryptographerTestVectorTest, EncryptionVectorsDraft03) {
321 std::string ecdh_shared_secret, salt, output, ciphertext;
286 size_t record_size = 0; 322 size_t record_size = 0;
287 323
288 for (size_t i = 0; i < arraysize(kEncryptionTestVectors); ++i) { 324 for (size_t i = 0; i < arraysize(kEncryptionTestVectorsDraft03); ++i) {
289 SCOPED_TRACE(i); 325 SCOPED_TRACE(i);
290 326
291 ASSERT_TRUE(base::Base64UrlDecode( 327 ASSERT_TRUE(base::Base64UrlDecode(
292 kEncryptionTestVectors[i].key, 328 kEncryptionTestVectorsDraft03[i].ecdh_shared_secret,
293 base::Base64UrlDecodePolicy::IGNORE_PADDING, &key)); 329 base::Base64UrlDecodePolicy::IGNORE_PADDING, &ecdh_shared_secret));
294 ASSERT_TRUE(base::Base64UrlDecode( 330 ASSERT_TRUE(base::Base64UrlDecode(
295 kEncryptionTestVectors[i].salt, 331 kEncryptionTestVectorsDraft03[i].salt,
296 base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt)); 332 base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt));
297 333
298 const bool has_output = kEncryptionTestVectors[i].output; 334 const bool has_output = kEncryptionTestVectorsDraft03[i].output;
299 const bool result = cryptographer()->Encrypt( 335 const bool result = cryptographer_->Encrypt(
300 kEncryptionTestVectors[i].input, key, salt, &record_size, &ciphertext); 336 recipient_public_key_, sender_public_key_, ecdh_shared_secret,
337 kCommonAuthSecret, salt, kEncryptionTestVectorsDraft03[i].input,
338 &record_size, &ciphertext);
301 339
302 if (!has_output) { 340 if (!has_output) {
303 EXPECT_FALSE(result); 341 EXPECT_FALSE(result);
304 continue; 342 continue;
305 } 343 }
306 344
307 EXPECT_TRUE(result); 345 EXPECT_TRUE(result);
308 ASSERT_TRUE(base::Base64UrlDecode( 346 ASSERT_TRUE(base::Base64UrlDecode(
309 kEncryptionTestVectors[i].output, 347 kEncryptionTestVectorsDraft03[i].output,
310 base::Base64UrlDecodePolicy::IGNORE_PADDING, &output)); 348 base::Base64UrlDecodePolicy::IGNORE_PADDING, &output));
311 349
312 EXPECT_EQ(kEncryptionTestVectors[i].record_size, record_size); 350 EXPECT_EQ(kEncryptionTestVectorsDraft03[i].record_size, record_size);
313 EXPECT_EQ(output, ciphertext); 351 EXPECT_EQ(output, ciphertext);
314 } 352 }
315 } 353 }
316 354
317 TEST_F(GCMMessageCryptographerTest, DecryptionTestVectors) { 355 TEST_F(GCMMessageCryptographerTestVectorTest, DecryptionVectorsDraft03) {
318 std::string input, key, salt, plaintext; 356 std::string input, ecdh_shared_secret, salt, plaintext;
319 for (size_t i = 0; i < arraysize(kDecryptionTestVectors); ++i) { 357 for (size_t i = 0; i < arraysize(kDecryptionTestVectorsDraft03); ++i) {
320 SCOPED_TRACE(i); 358 SCOPED_TRACE(i);
321 359
322 ASSERT_TRUE(base::Base64UrlDecode( 360 ASSERT_TRUE(base::Base64UrlDecode(
323 kDecryptionTestVectors[i].input, 361 kDecryptionTestVectorsDraft03[i].input,
324 base::Base64UrlDecodePolicy::IGNORE_PADDING, &input)); 362 base::Base64UrlDecodePolicy::IGNORE_PADDING, &input));
325 ASSERT_TRUE(base::Base64UrlDecode( 363 ASSERT_TRUE(base::Base64UrlDecode(
326 kDecryptionTestVectors[i].key, 364 kDecryptionTestVectorsDraft03[i].ecdh_shared_secret,
327 base::Base64UrlDecodePolicy::IGNORE_PADDING, &key)); 365 base::Base64UrlDecodePolicy::IGNORE_PADDING, &ecdh_shared_secret));
328 ASSERT_TRUE(base::Base64UrlDecode( 366 ASSERT_TRUE(base::Base64UrlDecode(
329 kDecryptionTestVectors[i].salt, 367 kDecryptionTestVectorsDraft03[i].salt,
330 base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt)); 368 base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt));
331 369
332 const bool has_output = kDecryptionTestVectors[i].output; 370 const bool has_output = kDecryptionTestVectorsDraft03[i].output;
333 const bool result = cryptographer()->Decrypt( 371 const bool result = cryptographer_->Decrypt(
334 input, key, salt, kDecryptionTestVectors[i].record_size, &plaintext); 372 recipient_public_key_, sender_public_key_, ecdh_shared_secret,
373 kCommonAuthSecret, salt, input,
374 kDecryptionTestVectorsDraft03[i].record_size, &plaintext);
335 375
336 if (!has_output) { 376 if (!has_output) {
337 EXPECT_FALSE(result); 377 EXPECT_FALSE(result);
338 continue; 378 continue;
339 } 379 }
340 380
341 EXPECT_TRUE(result); 381 EXPECT_TRUE(result);
342 EXPECT_EQ(kDecryptionTestVectors[i].output, plaintext); 382 EXPECT_EQ(kDecryptionTestVectorsDraft03[i].output, plaintext);
343 } 383 }
344 } 384 }
345 385
346 TEST_F(GCMMessageCryptographerTest, AuthSecretAffectsIKM) { 386 class GCMMessageCryptographerReferenceTest : public ::testing::Test {
347 std::string public_key;
348 ASSERT_TRUE(base::Base64UrlDecode(
349 kLocalPublicKeyCommon, base::Base64UrlDecodePolicy::IGNORE_PADDING,
350 &public_key));
351
352 // Fake IKM to use in the DerivePseudoRandomKey calls.
353 const char kFakeIKM[] = "HelloWorld";
354
355 GCMMessageCryptographer hello_cryptographer(public_key, public_key, "Hello");
356
357 GCMMessageCryptographer world_cryptographer(public_key, public_key, "World");
358
359 ASSERT_NE(hello_cryptographer.DerivePseudoRandomKey(kFakeIKM), kFakeIKM);
360 ASSERT_NE(world_cryptographer.DerivePseudoRandomKey(kFakeIKM), kFakeIKM);
361
362 ASSERT_NE(hello_cryptographer.DerivePseudoRandomKey(kFakeIKM),
363 world_cryptographer.DerivePseudoRandomKey(kFakeIKM));
364
365 std::string salt = GenerateRandomSalt();
366
367 // Verify that the IKM actually gets used by the transformations.
368 size_t hello_record_size, world_record_size;
369 std::string hello_ciphertext, world_ciphertext;
370
371 ASSERT_TRUE(hello_cryptographer.Encrypt(kExamplePlaintext, key(), salt,
372 &hello_record_size,
373 &hello_ciphertext));
374 ASSERT_TRUE(world_cryptographer.Encrypt(kExamplePlaintext, key(), salt,
375 &world_record_size,
376 &world_ciphertext));
377
378 // If the ciphertexts differ despite the same key and salt, it got used.
379 ASSERT_NE(hello_ciphertext, world_ciphertext);
380
381 // Verify that the different ciphertexts can also be translated back to the
382 // plaintext content. This will fail if the auth secret isn't considered.
383 std::string hello_plaintext, world_plaintext;
384
385 ASSERT_TRUE(hello_cryptographer.Decrypt(hello_ciphertext, key(), salt,
386 hello_record_size, &hello_plaintext));
387 ASSERT_TRUE(world_cryptographer.Decrypt(world_ciphertext, key(), salt,
388 world_record_size, &world_plaintext));
389
390 EXPECT_EQ(kExamplePlaintext, hello_plaintext);
391 EXPECT_EQ(kExamplePlaintext, world_plaintext);
392 }
393
394 // Common infrastructure for reference tests against the examples in the draft:
395 // https://tools.ietf.org/html/draft-thomson-http-encryption
396 class GCMMessageCryptographerReferenceTest
397 : public GCMMessageCryptographerTest {
398 protected: 387 protected:
399 // Computes the shared secret between the sender and the receiver. The sender 388 // Computes the shared secret between the sender and the receiver. The sender
400 // must have a key-pair containing a X.509 SubjectPublicKeyInfo block and a 389 // must have a key-pair containing a X.509 SubjectPublicKeyInfo block and a
401 // ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo block, whereas the receiver 390 // ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo block, whereas the receiver
402 // must have a public key in uncompressed EC point format. 391 // must have a public key in uncompressed EC point format.
403 void ComputeSharedSecret(const char* encoded_sender_private_key, 392 void ComputeSharedSecret(const char* encoded_sender_private_key,
404 const char* encoded_sender_public_key_x509, 393 const char* encoded_sender_public_key_x509,
405 const char* encoded_receiver_public_key, 394 const char* encoded_receiver_public_key,
406 std::string* shared_secret) const { 395 std::string* shared_secret) const {
407 std::string sender_private_key, sender_public_key_x509, receiver_public_key; 396 std::string sender_private_key, sender_public_key_x509, receiver_public_key;
408 ASSERT_TRUE(base::Base64UrlDecode( 397 ASSERT_TRUE(base::Base64UrlDecode(
409 encoded_sender_private_key, 398 encoded_sender_private_key,
410 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_private_key)); 399 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_private_key));
411 ASSERT_TRUE(base::Base64UrlDecode( 400 ASSERT_TRUE(base::Base64UrlDecode(
412 encoded_sender_public_key_x509, 401 encoded_sender_public_key_x509,
413 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_public_key_x509)); 402 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_public_key_x509));
414 ASSERT_TRUE(base::Base64UrlDecode( 403 ASSERT_TRUE(base::Base64UrlDecode(
415 encoded_receiver_public_key, 404 encoded_receiver_public_key,
416 base::Base64UrlDecodePolicy::IGNORE_PADDING, &receiver_public_key)); 405 base::Base64UrlDecodePolicy::IGNORE_PADDING, &receiver_public_key));
417 406
418 ASSERT_TRUE(ComputeSharedP256Secret( 407 ASSERT_TRUE(ComputeSharedP256Secret(
419 sender_private_key, sender_public_key_x509, receiver_public_key, 408 sender_private_key, sender_public_key_x509, receiver_public_key,
420 shared_secret)); 409 shared_secret));
421 } 410 }
422
423 // Creates a new cryptographer based on the P-256 curve with the given public
424 // keys of the sender and receiver, and optionally, the authentication secret.
425 // The public keys must be given as uncompressed P-256 EC points.
426 void CreateCryptographer(
427 const char* encoded_receiver_public_key,
428 const char* encoded_sender_public_key,
429 const char* encoded_auth_secret,
430 std::unique_ptr<GCMMessageCryptographer>* cryptographer) const {
431 std::string receiver_public_key, sender_public_key, auth_secret;
432 ASSERT_TRUE(base::Base64UrlDecode(
433 encoded_receiver_public_key,
434 base::Base64UrlDecodePolicy::IGNORE_PADDING, &receiver_public_key));
435 ASSERT_TRUE(base::Base64UrlDecode(
436 encoded_sender_public_key,
437 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_public_key));
438
439 if (encoded_auth_secret) {
440 ASSERT_TRUE(base::Base64UrlDecode(
441 encoded_auth_secret,
442 base::Base64UrlDecodePolicy::IGNORE_PADDING, &auth_secret));
443 }
444
445 std::unique_ptr<GCMMessageCryptographer> instance(
446 new GCMMessageCryptographer(receiver_public_key, sender_public_key,
447 auth_secret));
448
449 if (auth_secret.empty())
450 instance->set_allow_empty_auth_secret_for_tests(true);
451
452 cryptographer->swap(instance);
453 }
454 }; 411 };
455 412
456 TEST_F(GCMMessageCryptographerReferenceTest, WithAuthSecret) { 413 // Reference test included for the Version::DRAFT_03 implementation.
414 // https://tools.ietf.org/html/draft-ietf-webpush-encryption-03
415 // https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02
416 TEST_F(GCMMessageCryptographerReferenceTest, ReferenceDraft03) {
457 // The 16-byte salt unique to the message. 417 // The 16-byte salt unique to the message.
458 const char kSalt[] = "lngarbyKfMoi9Z75xYXmkg"; 418 const char kSalt[] = "lngarbyKfMoi9Z75xYXmkg";
459 419
460 // The 16-byte prearranged secret between the sender and receiver. 420 // The 16-byte prearranged secret between the sender and receiver.
461 const char kAuthSecret[] = "R29vIGdvbyBnJyBqb29iIQ"; 421 const char kAuthSecret[] = "R29vIGdvbyBnJyBqb29iIQ";
462 422
463 // The keying material used by the sender to encrypt the |kCiphertext|. 423 // The keying material used by the sender to encrypt the |kCiphertext|.
464 const char kSenderPrivate[] = 424 const char kSenderPrivate[] =
465 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIh9aZ3UvuDloCAggABIGQZ-T8CJZe-no4mOTDgX1Gm986" 425 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIh9aZ3UvuDloCAggABIGQZ-T8CJZe-no4mOTDgX1Gm986"
466 "Gsbe3mjJeABhA4KOmut_qJh5kt_DLqdNShiQr-afk3AdkX-fxLZdrcHiW9aWvBjnMAY65zg5" 426 "Gsbe3mjJeABhA4KOmut_qJh5kt_DLqdNShiQr-afk3AdkX-fxLZdrcHiW9aWvBjnMAY65zg5"
467 "oHsuUaoEuG88Ksbku2u193OENWTQTsYaYE2O44qmRfsX773UNVcWXg_omwIbhbgf6tLZUZH_" 427 "oHsuUaoEuG88Ksbku2u193OENWTQTsYaYE2O44qmRfsX773UNVcWXg_omwIbhbgf6tLZUZH_"
468 "dTC3YjzuxjbSP89HPEJ-eBXA"; 428 "dTC3YjzuxjbSP89HPEJ-eBXA";
469 const char kSenderPublicUncompressed[] = 429 const char kSenderPublicKeyUncompressed[] =
470 "BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6D" 430 "BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6D"
471 "PpDrWtdWj_mugHU"; 431 "PpDrWtdWj_mugHU";
472 const char kSenderPublicX509[] = 432 const char kSenderPublicX509[] =
473 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2hENtvzgkabyDlnkIXG6tKqxdYnXUi19cRZh" 433 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2hENtvzgkabyDlnkIXG6tKqxdYnXUi19cRZh"
474 "UsTzljsJiQONewgRzhqrFhpDUbwGqRcInoM-kOta11aP-a6AdQ"; 434 "UsTzljsJiQONewgRzhqrFhpDUbwGqRcInoM-kOta11aP-a6AdQ";
475 435
476 // The keying material used by the client to decrypt the |kCiphertext|. 436 // The keying material used by the recipient to decrypt the |kCiphertext|.
477 const char kReceiverPrivate[] = 437 const char kRecipientPrivate[] =
478 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIqMt4d7uJdt4CAggABIGQeikRHE3CqUeF-uUtJno9BL0g" 438 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIqMt4d7uJdt4CAggABIGQeikRHE3CqUeF-uUtJno9BL0g"
479 "mNRyDihZe8P3nF_g-NYVzvdQowsXfYeza6OQOdDuMXxnGgNToVy2jsiWVN6rxCaSMTY622y8" 439 "mNRyDihZe8P3nF_g-NYVzvdQowsXfYeza6OQOdDuMXxnGgNToVy2jsiWVN6rxCaSMTY622y8"
480 "ajW5voSdqC2PakQ8ZNTPNHarLDMC9NpgGKrUh8hfRLhvb7vtbKIWmx-22rQB5yTYdqzN2m7A" 440 "ajW5voSdqC2PakQ8ZNTPNHarLDMC9NpgGKrUh8hfRLhvb7vtbKIWmx-22rQB5yTYdqzN2m7A"
481 "GHMWRnVk0mMzMsMjZqYFaa2D"; 441 "GHMWRnVk0mMzMsMjZqYFaa2D";
482 const char kReceiverPublicUncompressed[] = 442 const char kRecipientPublicKeyUncompressed[] =
483 "BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3" 443 "BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3"
484 "il2nNZct4HgAUQU"; 444 "il2nNZct4HgAUQU";
485 const char kReceiverPublicX509[] = 445 const char kRecipientPublicX509[] =
486 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3ep" 446 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3ep"
487 "Q_TC-pFPbUQRbJ_RxANBxqRAyrPiFApg5DeKXac1ly3geABRBQ"; 447 "Q_TC-pFPbUQRbJ_RxANBxqRAyrPiFApg5DeKXac1ly3geABRBQ";
488 448
489 // The ciphertext and associated plaintext of the message. 449 // The ciphertext and associated plaintext of the message.
490 const char kCiphertext[] = "6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA"; 450 const char kCiphertext[] = "6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA";
491 const char kPlaintext[] = "I am the walrus"; 451 const char kPlaintext[] = "I am the walrus";
492 452
493 std::string sender_shared_secret, receiver_shared_secret; 453 std::string sender_shared_secret, receiver_shared_secret;
494 454
495 // Compute the shared secrets between the sender and receiver's keys. 455 // Compute the shared secrets between the sender and receiver's keys.
456 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(kSenderPrivate, kSenderPublicX509,
457 kRecipientPublicKeyUncompressed,
458 &sender_shared_secret));
496 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret( 459 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(
497 kSenderPrivate, kSenderPublicX509, kReceiverPublicUncompressed, 460 kRecipientPrivate, kRecipientPublicX509, kSenderPublicKeyUncompressed,
498 &sender_shared_secret));
499 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(
500 kReceiverPrivate, kReceiverPublicX509, kSenderPublicUncompressed,
501 &receiver_shared_secret)); 461 &receiver_shared_secret));
502 462
503 ASSERT_GT(sender_shared_secret.size(), 0u); 463 ASSERT_GT(sender_shared_secret.size(), 0u);
504 ASSERT_EQ(sender_shared_secret, receiver_shared_secret); 464 ASSERT_EQ(sender_shared_secret, receiver_shared_secret);
505 465
506 std::unique_ptr<GCMMessageCryptographer> cryptographer; 466 // Decode the public keys of both parties, the auth secret and the salt.
507 ASSERT_NO_FATAL_FAILURE(CreateCryptographer( 467 std::string recipient_public_key, sender_public_key, auth_secret, salt;
508 kReceiverPublicUncompressed, kSenderPublicUncompressed, kAuthSecret, 468 ASSERT_TRUE(base::Base64UrlDecode(kRecipientPublicKeyUncompressed,
509 &cryptographer)); 469 base::Base64UrlDecodePolicy::IGNORE_PADDING,
510 470 &recipient_public_key));
511 std::string salt; 471 ASSERT_TRUE(base::Base64UrlDecode(kSenderPublicKeyUncompressed,
472 base::Base64UrlDecodePolicy::IGNORE_PADDING,
473 &sender_public_key));
474 ASSERT_TRUE(base::Base64UrlDecode(
475 kAuthSecret, base::Base64UrlDecodePolicy::IGNORE_PADDING, &auth_secret));
512 ASSERT_TRUE(base::Base64UrlDecode( 476 ASSERT_TRUE(base::Base64UrlDecode(
513 kSalt, base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt)); 477 kSalt, base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt));
514 478
515 std::string encoded_ciphertext, ciphertext, plaintext; 479 std::string encoded_ciphertext, ciphertext, plaintext;
516 size_t record_size = 0; 480 size_t record_size = 0;
517 481
518 // Verify that encrypting |kPlaintext| yields the expected |kCiphertext|. 482 // Now verify that encrypting a message with the given information yields the
519 ASSERT_TRUE(cryptographer->Encrypt(kPlaintext, sender_shared_secret, salt, 483 // expected ciphertext given the defined input.
520 &record_size, &ciphertext)); 484 GCMMessageCryptographer cryptographer(
485 GCMMessageCryptographer::Version::DRAFT_03);
486
487 ASSERT_TRUE(cryptographer.Encrypt(recipient_public_key, sender_public_key,
488 sender_shared_secret, auth_secret, salt,
489 kPlaintext, &record_size, &ciphertext));
521 490
522 base::Base64UrlEncode(ciphertext, base::Base64UrlEncodePolicy::OMIT_PADDING, 491 base::Base64UrlEncode(ciphertext, base::Base64UrlEncodePolicy::OMIT_PADDING,
523 &encoded_ciphertext); 492 &encoded_ciphertext);
524 ASSERT_EQ(kCiphertext, encoded_ciphertext); 493 ASSERT_EQ(kCiphertext, encoded_ciphertext);
525 494
526 // Verify that decrypting |kCiphertext| yields the expected |kPlaintext|. 495 // And verify that decrypting themessageyields the plaintext again.
martijnc 2017/03/28 16:26:36 typo: missing spaces
Peter Beverloo 2017/04/07 17:48:22 What how. Fixed, thanks!
527 ASSERT_TRUE(cryptographer->Decrypt(ciphertext, sender_shared_secret, salt, 496 ASSERT_TRUE(cryptographer.Decrypt(recipient_public_key, sender_public_key,
528 record_size, &plaintext)); 497 sender_shared_secret, auth_secret, salt,
498 ciphertext, record_size, &plaintext));
499
529 ASSERT_EQ(kPlaintext, plaintext); 500 ASSERT_EQ(kPlaintext, plaintext);
530 } 501 }
531 502
532 TEST_F(GCMMessageCryptographerReferenceTest, WithoutAuthSecret) {
533 // The 16-byte salt unique to the message.
534 const char kSalt[] = "Qg61ZJRva_XBE9IEUelU3A";
535
536 // The keying material used by the sender to encrypt the |kCiphertext|.
537 const char kSenderPrivate[] =
538 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIFfJ62c9VwXgCAggABIGQkRxDRPQjwuWp1C3-z1pYTDqF"
539 "_NZ1kbPsjmkC3JSv02oAYHtBAtKa2e3oAPqsPfCvoCJBJs6G4WY4EuEO1YFL6RKpNl3DpIUc"
540 "v9ShR27p_je_nyLpNBAxn2drnjlF_K6s4gcJmcvCxuNjAwOlLMPvQqGjOR2K_oMs1Hdq0EKJ"
541 "NwWt3WUVEpuQF_WhYjCVIeGO";
542 const char kSenderPublicUncompressed[] =
543 "BDgpRKok2GZZDmS4r63vbJSUtcQx4Fq1V58-6-3NbZzSTlZsQiCEDTQy3CZ0ZMsqeqsEb7qW"
544 "2blQHA4S48fynTk";
545 const char kSenderPublicX509[] =
546 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOClEqiTYZlkOZLivre9slJS1xDHgWrVXnz7r"
547 "7c1tnNJOVmxCIIQNNDLcJnRkyyp6qwRvupbZuVAcDhLjx_KdOQ";
548
549 // The keying material used by the client to decrypt the |kCiphertext|.
550 const char kReceiverPrivate[] =
551 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIqMt4d7uJdt4CAggABIGQeikRHE3CqUeF-uUtJno9BL0g"
552 "mNRyDihZe8P3nF_g-NYVzvdQowsXfYeza6OQOdDuMXxnGgNToVy2jsiWVN6rxCaSMTY622y8"
553 "ajW5voSdqC2PakQ8ZNTPNHarLDMC9NpgGKrUh8hfRLhvb7vtbKIWmx-22rQB5yTYdqzN2m7A"
554 "GHMWRnVk0mMzMsMjZqYFaa2D";
555 const char kReceiverPublicUncompressed[] =
556 "BCEkBjzL8Z3C-oi2Q7oE5t2Np-p7osjGLg93qUP0wvqRT21EEWyf0cQDQcakQMqz4hQKYOQ3"
557 "il2nNZct4HgAUQU";
558 const char kReceiverPublicX509[] =
559 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEISQGPMvxncL6iLZDugTm3Y2n6nuiyMYuD3ep"
560 "Q_TC-pFPbUQRbJ_RxANBxqRAyrPiFApg5DeKXac1ly3geABRBQ";
561
562 // The ciphertext and associated plaintext of the message.
563 const char kCiphertext[] = "yqD2bapcx14XxUbtwjiGx69eHE3Yd6AqXcwBpT2Kd1uy";
564 const char kPlaintext[] = "I am the walrus";
565
566 std::string sender_shared_secret, receiver_shared_secret;
567
568 // Compute the shared secrets between the sender and receiver's keys.
569 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(
570 kSenderPrivate, kSenderPublicX509, kReceiverPublicUncompressed,
571 &sender_shared_secret));
572 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(
573 kReceiverPrivate, kReceiverPublicX509, kSenderPublicUncompressed,
574 &receiver_shared_secret));
575
576 ASSERT_GT(sender_shared_secret.size(), 0u);
577 ASSERT_EQ(sender_shared_secret, receiver_shared_secret);
578
579 std::unique_ptr<GCMMessageCryptographer> cryptographer;
580 ASSERT_NO_FATAL_FAILURE(CreateCryptographer(
581 kReceiverPublicUncompressed, kSenderPublicUncompressed,
582 nullptr /* auth_secret */, &cryptographer));
583
584 std::string salt;
585 ASSERT_TRUE(base::Base64UrlDecode(
586 kSalt, base::Base64UrlDecodePolicy::IGNORE_PADDING, &salt));
587
588 std::string encoded_ciphertext, ciphertext, plaintext;
589 size_t record_size = 0;
590
591 // Verify that encrypting |kPlaintext| yields the expected |kCiphertext|.
592 ASSERT_TRUE(cryptographer->Encrypt(kPlaintext, sender_shared_secret, salt,
593 &record_size, &ciphertext));
594
595 base::Base64UrlEncode(ciphertext, base::Base64UrlEncodePolicy::OMIT_PADDING,
596 &encoded_ciphertext);
597 ASSERT_EQ(kCiphertext, encoded_ciphertext);
598
599 // Verify that decrypting |kCiphertext| yields the expected |kPlaintext|.
600 ASSERT_TRUE(cryptographer->Decrypt(ciphertext, sender_shared_secret, salt,
601 record_size, &plaintext));
602 ASSERT_EQ(kPlaintext, plaintext);
603 }
604
605 } // namespace gcm 503 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698