1 // Copyright (c) 2011 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 "crypto/symmetric_key.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
TEST(SymmetricKeyTest,GenerateRandomKey)14 TEST(SymmetricKeyTest, GenerateRandomKey) {
15 std::unique_ptr<crypto::SymmetricKey> key(
16 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
17 ASSERT_TRUE(key);
18 std::string raw_key;
19 EXPECT_TRUE(key->GetRawKey(&raw_key));
20 EXPECT_EQ(32U, raw_key.size());
21
22 // Do it again and check that the keys are different.
23 // (Note: this has a one-in-10^77 chance of failure!)
24 std::unique_ptr<crypto::SymmetricKey> key2(
25 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
26 ASSERT_TRUE(key2);
27 std::string raw_key2;
28 EXPECT_TRUE(key2->GetRawKey(&raw_key2));
29 EXPECT_EQ(32U, raw_key2.size());
30 EXPECT_NE(raw_key, raw_key2);
31 }
32
TEST(SymmetricKeyTest,ImportGeneratedKey)33 TEST(SymmetricKeyTest, ImportGeneratedKey) {
34 std::unique_ptr<crypto::SymmetricKey> key1(
35 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
36 ASSERT_TRUE(key1);
37 std::string raw_key1;
38 EXPECT_TRUE(key1->GetRawKey(&raw_key1));
39
40 std::unique_ptr<crypto::SymmetricKey> key2(
41 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1));
42 ASSERT_TRUE(key2);
43
44 std::string raw_key2;
45 EXPECT_TRUE(key2->GetRawKey(&raw_key2));
46
47 EXPECT_EQ(raw_key1, raw_key2);
48 }
49
TEST(SymmetricKeyTest,ImportDerivedKey)50 TEST(SymmetricKeyTest, ImportDerivedKey) {
51 std::unique_ptr<crypto::SymmetricKey> key1(
52 crypto::SymmetricKey::DeriveKeyFromPassword(
53 crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160));
54 ASSERT_TRUE(key1);
55 std::string raw_key1;
56 EXPECT_TRUE(key1->GetRawKey(&raw_key1));
57
58 std::unique_ptr<crypto::SymmetricKey> key2(
59 crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1));
60 ASSERT_TRUE(key2);
61
62 std::string raw_key2;
63 EXPECT_TRUE(key2->GetRawKey(&raw_key2));
64
65 EXPECT_EQ(raw_key1, raw_key2);
66 }
67
68 struct PBKDF2TestVector {
69 crypto::SymmetricKey::Algorithm algorithm;
70 const char* password;
71 const char* salt;
72 unsigned int rounds;
73 unsigned int key_size_in_bits;
74 const char* expected; // ASCII encoded hex bytes
75 };
76
77 class SymmetricKeyDeriveKeyFromPasswordTest
78 : public testing::TestWithParam<PBKDF2TestVector> {
79 };
80
TEST_P(SymmetricKeyDeriveKeyFromPasswordTest,DeriveKeyFromPassword)81 TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) {
82 PBKDF2TestVector test_data(GetParam());
83 std::unique_ptr<crypto::SymmetricKey> key(
84 crypto::SymmetricKey::DeriveKeyFromPassword(
85 test_data.algorithm, test_data.password, test_data.salt,
86 test_data.rounds, test_data.key_size_in_bits));
87 ASSERT_TRUE(key);
88
89 std::string raw_key;
90 key->GetRawKey(&raw_key);
91 EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size());
92 EXPECT_EQ(test_data.expected,
93 base::ToLowerASCII(base::HexEncode(raw_key.data(),
94 raw_key.size())));
95 }
96
97 static const PBKDF2TestVector kTestVectors[] = {
98 // These tests come from
99 // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt
100 {
101 crypto::SymmetricKey::HMAC_SHA1,
102 "password",
103 "salt",
104 1,
105 160,
106 "0c60c80f961f0e71f3a9b524af6012062fe037a6",
107 },
108 {
109 crypto::SymmetricKey::HMAC_SHA1,
110 "password",
111 "salt",
112 2,
113 160,
114 "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
115 },
116 {
117 crypto::SymmetricKey::HMAC_SHA1,
118 "password",
119 "salt",
120 4096,
121 160,
122 "4b007901b765489abead49d926f721d065a429c1",
123 },
124 // This test takes over 30s to run on the trybots.
125 #if 0
126 {
127 crypto::SymmetricKey::HMAC_SHA1,
128 "password",
129 "salt",
130 16777216,
131 160,
132 "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984",
133 },
134 #endif
135
136 // These tests come from RFC 3962, via BSD source code at
137 // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain
138 {
139 crypto::SymmetricKey::HMAC_SHA1,
140 "password",
141 "ATHENA.MIT.EDUraeburn",
142 1,
143 160,
144 "cdedb5281bb2f801565a1122b25635150ad1f7a0",
145 },
146 {
147 crypto::SymmetricKey::HMAC_SHA1,
148 "password",
149 "ATHENA.MIT.EDUraeburn",
150 2,
151 160,
152 "01dbee7f4a9e243e988b62c73cda935da05378b9",
153 },
154 {
155 crypto::SymmetricKey::HMAC_SHA1,
156 "password",
157 "ATHENA.MIT.EDUraeburn",
158 1200,
159 160,
160 "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb",
161 },
162 {
163 crypto::SymmetricKey::HMAC_SHA1,
164 "password",
165 "\022" "4VxxV4\022", /* 0x1234567878563412 */
166 5,
167 160,
168 "d1daa78615f287e6a1c8b120d7062a493f98d203",
169 },
170 {
171 crypto::SymmetricKey::HMAC_SHA1,
172 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
173 "pass phrase equals block size",
174 1200,
175 160,
176 "139c30c0966bc32ba55fdbf212530ac9c5ec59f1",
177 },
178 {
179 crypto::SymmetricKey::HMAC_SHA1,
180 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
181 "pass phrase exceeds block size",
182 1200,
183 160,
184 "9ccad6d468770cd51b10e6a68721be611a8b4d28",
185 },
186 {
187 crypto::SymmetricKey::HMAC_SHA1,
188 "\360\235\204\236", /* g-clef (0xf09d849e) */
189 "EXAMPLE.COMpianist",
190 50,
191 160,
192 "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0",
193 },
194
195 // Regression tests for AES keys, derived from the Linux NSS implementation.
196 {
197 crypto::SymmetricKey::AES,
198 "A test password",
199 "saltsalt",
200 1,
201 256,
202 "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de",
203 },
204 {
205 crypto::SymmetricKey::AES,
206 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
207 "pass phrase exceeds block size",
208 20,
209 256,
210 "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c",
211 },
212 };
213
214 INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest,
215 testing::ValuesIn(kTestVectors));
216