OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/crypto/symmetric_key.h" | 5 #include "base/crypto/symmetric_key.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
| 9 #include "base/string_number_conversions.h" |
9 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
12 | 13 |
13 TEST(SymmetricKeyTest, GenerateRandomKey) { | 14 TEST(SymmetricKeyTest, GenerateRandomKey) { |
14 scoped_ptr<base::SymmetricKey> key( | 15 scoped_ptr<base::SymmetricKey> key( |
15 base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); | 16 base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); |
16 ASSERT_TRUE(NULL != key.get()); | 17 ASSERT_TRUE(NULL != key.get()); |
17 std::string raw_key; | 18 std::string raw_key; |
18 EXPECT_TRUE(key->GetRawKey(&raw_key)); | 19 EXPECT_TRUE(key->GetRawKey(&raw_key)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 base::SymmetricKey::Import(base::SymmetricKey::HMAC_SHA1, raw_key1)); | 60 base::SymmetricKey::Import(base::SymmetricKey::HMAC_SHA1, raw_key1)); |
60 ASSERT_TRUE(NULL != key2.get()); | 61 ASSERT_TRUE(NULL != key2.get()); |
61 | 62 |
62 std::string raw_key2; | 63 std::string raw_key2; |
63 EXPECT_TRUE(key2->GetRawKey(&raw_key2)); | 64 EXPECT_TRUE(key2->GetRawKey(&raw_key2)); |
64 | 65 |
65 EXPECT_EQ(raw_key1, raw_key2); | 66 EXPECT_EQ(raw_key1, raw_key2); |
66 } | 67 } |
67 | 68 |
68 struct PBKDF2TestVector { | 69 struct PBKDF2TestVector { |
69 const char* password; | 70 base::SymmetricKey::Algorithm algorithm; |
70 const char* salt; | 71 const char* const password; |
| 72 const char* const salt; |
71 unsigned int rounds; | 73 unsigned int rounds; |
72 unsigned int key_size_in_bits; | 74 unsigned int key_size_in_bits; |
73 const uint8 expected[21]; // string literals need 1 extra NUL byte | 75 const char* const expected; // ASCII encoded hex bytes |
74 }; | 76 }; |
75 | 77 |
76 static const PBKDF2TestVector test_vectors[] = { | 78 class SymmetricKeyDeriveKeyFromPasswordTest |
| 79 : public testing::TestWithParam<PBKDF2TestVector> { |
| 80 }; |
| 81 |
| 82 TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { |
| 83 PBKDF2TestVector test_data(GetParam()); |
| 84 #if defined(OS_MACOSX) |
| 85 // The OS X crypto libraries have minimum salt and iteration requirements |
| 86 // so some of the above tests will cause them to barf. Skip these. |
| 87 if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { |
| 88 VLOG(1) << "Skipped test vector #" << i; |
| 89 return; |
| 90 } |
| 91 #endif // OS_MACOSX |
| 92 |
| 93 scoped_ptr<base::SymmetricKey> key( |
| 94 base::SymmetricKey::DeriveKeyFromPassword( |
| 95 test_data.algorithm, |
| 96 test_data.password, test_data.salt, |
| 97 test_data.rounds, test_data.key_size_in_bits)); |
| 98 ASSERT_TRUE(NULL != key.get()); |
| 99 |
| 100 std::string raw_key; |
| 101 key->GetRawKey(&raw_key); |
| 102 EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); |
| 103 EXPECT_EQ(test_data.expected, |
| 104 StringToLowerASCII(base::HexEncode(raw_key.data(), |
| 105 raw_key.size()))); |
| 106 } |
| 107 |
| 108 static const PBKDF2TestVector kTestVectors[] = { |
77 // These tests come from | 109 // These tests come from |
78 // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt | 110 // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt |
79 { | 111 { |
| 112 base::SymmetricKey::HMAC_SHA1, |
80 "password", | 113 "password", |
81 "salt", | 114 "salt", |
82 1, | 115 1, |
83 160, | 116 160, |
84 "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" | 117 "0c60c80f961f0e71f3a9b524af6012062fe037a6", |
85 "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", | |
86 }, | 118 }, |
87 { | 119 { |
| 120 base::SymmetricKey::HMAC_SHA1, |
88 "password", | 121 "password", |
89 "salt", | 122 "salt", |
90 2, | 123 2, |
91 160, | 124 160, |
92 "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e" | 125 "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", |
93 "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", | |
94 }, | 126 }, |
95 { | 127 { |
| 128 base::SymmetricKey::HMAC_SHA1, |
96 "password", | 129 "password", |
97 "salt", | 130 "salt", |
98 4096, | 131 4096, |
99 160, | 132 160, |
100 "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad" | 133 "4b007901b765489abead49d926f721d065a429c1", |
101 "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", | |
102 }, | 134 }, |
103 // This test takes over 30s to run on the trybots. | 135 // This test takes over 30s to run on the trybots. |
104 #if 0 | 136 #if 0 |
105 { | 137 { |
| 138 base::SymmetricKey::HMAC_SHA1, |
106 "password", | 139 "password", |
107 "salt", | 140 "salt", |
108 16777216, | 141 16777216, |
109 160, | 142 160, |
110 "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94" | 143 "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", |
111 "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", | |
112 }, | 144 }, |
113 #endif | 145 #endif |
114 | 146 |
115 // These tests come from RFC 3962, via BSD source code at | 147 // These tests come from RFC 3962, via BSD source code at |
116 // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&con
tent-type=text/plain | 148 // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&con
tent-type=text/plain |
117 { | 149 { |
| 150 base::SymmetricKey::HMAC_SHA1, |
118 "password", | 151 "password", |
119 "ATHENA.MIT.EDUraeburn", | 152 "ATHENA.MIT.EDUraeburn", |
120 1, | 153 1, |
121 160, | 154 160, |
122 { | 155 "cdedb5281bb2f801565a1122b25635150ad1f7a0", |
123 0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, | |
124 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15, | |
125 0x0a, 0xd1, 0xf7, 0xa0 | |
126 }, | |
127 }, | 156 }, |
128 { | 157 { |
| 158 base::SymmetricKey::HMAC_SHA1, |
129 "password", | 159 "password", |
130 "ATHENA.MIT.EDUraeburn", | 160 "ATHENA.MIT.EDUraeburn", |
131 2, | 161 2, |
132 160, | 162 160, |
133 { | 163 "01dbee7f4a9e243e988b62c73cda935da05378b9", |
134 0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e, | |
135 0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d, | |
136 0xa0, 0x53, 0x78, 0xb9 | |
137 }, | |
138 }, | 164 }, |
139 { | 165 { |
| 166 base::SymmetricKey::HMAC_SHA1, |
140 "password", | 167 "password", |
141 "ATHENA.MIT.EDUraeburn", | 168 "ATHENA.MIT.EDUraeburn", |
142 1200, | 169 1200, |
143 160, | 170 160, |
144 { | 171 "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", |
145 0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, | |
146 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b, | |
147 0xa7, 0xe5, 0x2d, 0xdb | |
148 }, | |
149 }, | 172 }, |
150 { | 173 { |
| 174 base::SymmetricKey::HMAC_SHA1, |
151 "password", | 175 "password", |
152 "\0224VxxV4\022", /* 0x1234567878563412 */ | 176 "\0224VxxV4\022", /* 0x1234567878563412 */ |
153 5, | 177 5, |
154 160, | 178 160, |
155 { | 179 "d1daa78615f287e6a1c8b120d7062a493f98d203", |
156 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, | |
157 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49, | |
158 0x3f, 0x98, 0xd2, 0x03 | |
159 }, | |
160 }, | 180 }, |
161 { | 181 { |
| 182 base::SymmetricKey::HMAC_SHA1, |
162 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", | 183 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", |
163 "pass phrase equals block size", | 184 "pass phrase equals block size", |
164 1200, | 185 1200, |
165 160, | 186 160, |
166 { | 187 "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", |
167 0x13, 0x9c, 0x30, 0xc0, 0x96, 0x6b, 0xc3, 0x2b, | |
168 0xa5, 0x5f, 0xdb, 0xf2, 0x12, 0x53, 0x0a, 0xc9, | |
169 0xc5, 0xec, 0x59, 0xf1 | |
170 }, | |
171 }, | 188 }, |
172 { | 189 { |
| 190 base::SymmetricKey::HMAC_SHA1, |
173 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", | 191 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", |
174 "pass phrase exceeds block size", | 192 "pass phrase exceeds block size", |
175 1200, | 193 1200, |
176 160, | 194 160, |
177 { | 195 "9ccad6d468770cd51b10e6a68721be611a8b4d28", |
178 0x9c, 0xca, 0xd6, 0xd4, 0x68, 0x77, 0x0c, 0xd5, | |
179 0x1b, 0x10, 0xe6, 0xa6, 0x87, 0x21, 0xbe, 0x61, | |
180 0x1a, 0x8b, 0x4d, 0x28 | |
181 }, | |
182 }, | 196 }, |
183 { | 197 { |
| 198 base::SymmetricKey::HMAC_SHA1, |
184 "\360\235\204\236", /* g-clef (0xf09d849e) */ | 199 "\360\235\204\236", /* g-clef (0xf09d849e) */ |
185 "EXAMPLE.COMpianist", | 200 "EXAMPLE.COMpianist", |
186 50, | 201 50, |
187 160, | 202 160, |
188 { | 203 "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", |
189 0x6b, 0x9c, 0xf2, 0x6d, 0x45, 0x45, 0x5a, 0x43, | 204 }, |
190 0xa5, 0xb8, 0xbb, 0x27, 0x6a, 0x40, 0x3b, 0x39, | 205 |
191 0xe7, 0xfe, 0x37, 0xa0 | 206 // Regression tests for AES keys, derived from the Linux NSS implementation. |
192 }, | 207 { |
193 } | 208 base::SymmetricKey::AES, |
| 209 "A test password", |
| 210 "saltsalt", |
| 211 1, |
| 212 256, |
| 213 "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", |
| 214 }, |
| 215 { |
| 216 base::SymmetricKey::AES, |
| 217 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", |
| 218 "pass phrase exceeds block size", |
| 219 20, |
| 220 256, |
| 221 "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", |
| 222 }, |
194 }; | 223 }; |
195 | 224 |
196 TEST(SymmetricKeyTest, DeriveKeyFromPassword) { | 225 INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, |
197 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_vectors); ++i) { | 226 testing::ValuesIn(kTestVectors)); |
198 SCOPED_TRACE(StringPrintf("Test[%u]", i)); | |
199 #if defined(OS_MACOSX) | |
200 // The OS X crypto libraries have minimum salt and iteration requirements | |
201 // so some of the above tests will cause them to barf. Skip these. | |
202 if (strlen(test_vectors[i].salt) < 8 || test_vectors[i].rounds < 1000) { | |
203 VLOG(1) << "Skipped test vector #" << i; | |
204 continue; | |
205 } | |
206 #endif // OS_MACOSX | |
207 scoped_ptr<base::SymmetricKey> key( | |
208 base::SymmetricKey::DeriveKeyFromPassword( | |
209 base::SymmetricKey::HMAC_SHA1, | |
210 test_vectors[i].password, test_vectors[i].salt, | |
211 test_vectors[i].rounds, test_vectors[i].key_size_in_bits)); | |
212 ASSERT_TRUE(NULL != key.get()); | |
213 | |
214 std::string raw_key; | |
215 key->GetRawKey(&raw_key); | |
216 EXPECT_EQ(test_vectors[i].key_size_in_bits / 8, raw_key.size()); | |
217 EXPECT_EQ(0, memcmp(test_vectors[i].expected, | |
218 raw_key.data(), | |
219 raw_key.size())); | |
220 } | |
221 } | |
OLD | NEW |