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 <string> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "base/string_number_conversions.h" 11 #include "base/string_util.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 TEST(SymmetricKeyTest, GenerateRandomKey) { 15 scoped_ptr<crypto::SymmetricKey> key( 16 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); 17 ASSERT_TRUE(NULL != key.get()); 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 scoped_ptr<crypto::SymmetricKey> key2( 25 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); 26 ASSERT_TRUE(NULL != key2.get()); 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 33 TEST(SymmetricKeyTest, ImportGeneratedKey) { 34 scoped_ptr<crypto::SymmetricKey> key1( 35 crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256)); 36 ASSERT_TRUE(NULL != key1.get()); 37 std::string raw_key1; 38 EXPECT_TRUE(key1->GetRawKey(&raw_key1)); 39 40 scoped_ptr<crypto::SymmetricKey> key2( 41 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1)); 42 ASSERT_TRUE(NULL != key2.get()); 43 44 std::string raw_key2; 45 EXPECT_TRUE(key2->GetRawKey(&raw_key2)); 46 47 EXPECT_EQ(raw_key1, raw_key2); 48 } 49 50 TEST(SymmetricKeyTest, ImportDerivedKey) { 51 scoped_ptr<crypto::SymmetricKey> key1( 52 crypto::SymmetricKey::DeriveKeyFromPassword( 53 crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160)); 54 ASSERT_TRUE(NULL != key1.get()); 55 std::string raw_key1; 56 EXPECT_TRUE(key1->GetRawKey(&raw_key1)); 57 58 scoped_ptr<crypto::SymmetricKey> key2( 59 crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1)); 60 ASSERT_TRUE(NULL != key2.get()); 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 81 TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { 82 PBKDF2TestVector test_data(GetParam()); 83 #if defined(OS_MACOSX) 84 // The OS X crypto libraries have minimum salt and iteration requirements 85 // so some of the tests below will cause them to barf. Skip these. 86 if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) { 87 VLOG(1) << "Skipped test vector for " << test_data.expected; 88 return; 89 } 90 #endif // OS_MACOSX 91 92 scoped_ptr<crypto::SymmetricKey> key( 93 crypto::SymmetricKey::DeriveKeyFromPassword( 94 test_data.algorithm, 95 test_data.password, test_data.salt, 96 test_data.rounds, test_data.key_size_in_bits)); 97 ASSERT_TRUE(NULL != key.get()); 98 99 std::string raw_key; 100 key->GetRawKey(&raw_key); 101 EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); 102 EXPECT_EQ(test_data.expected, 103 StringToLowerASCII(base::HexEncode(raw_key.data(), 104 raw_key.size()))); 105 } 106 107 static const PBKDF2TestVector kTestVectors[] = { 108 // These tests come from 109 // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt 110 { 111 crypto::SymmetricKey::HMAC_SHA1, 112 "password", 113 "salt", 114 1, 115 160, 116 "0c60c80f961f0e71f3a9b524af6012062fe037a6", 117 }, 118 { 119 crypto::SymmetricKey::HMAC_SHA1, 120 "password", 121 "salt", 122 2, 123 160, 124 "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 125 }, 126 { 127 crypto::SymmetricKey::HMAC_SHA1, 128 "password", 129 "salt", 130 4096, 131 160, 132 "4b007901b765489abead49d926f721d065a429c1", 133 }, 134 // This test takes over 30s to run on the trybots. 135 #if 0 136 { 137 crypto::SymmetricKey::HMAC_SHA1, 138 "password", 139 "salt", 140 16777216, 141 160, 142 "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984", 143 }, 144 #endif 145 146 // These tests come from RFC 3962, via BSD source code at 147 // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain 148 { 149 crypto::SymmetricKey::HMAC_SHA1, 150 "password", 151 "ATHENA.MIT.EDUraeburn", 152 1, 153 160, 154 "cdedb5281bb2f801565a1122b25635150ad1f7a0", 155 }, 156 { 157 crypto::SymmetricKey::HMAC_SHA1, 158 "password", 159 "ATHENA.MIT.EDUraeburn", 160 2, 161 160, 162 "01dbee7f4a9e243e988b62c73cda935da05378b9", 163 }, 164 { 165 crypto::SymmetricKey::HMAC_SHA1, 166 "password", 167 "ATHENA.MIT.EDUraeburn", 168 1200, 169 160, 170 "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb", 171 }, 172 { 173 crypto::SymmetricKey::HMAC_SHA1, 174 "password", 175 "\0224VxxV4\022", /* 0x1234567878563412 */ 176 5, 177 160, 178 "d1daa78615f287e6a1c8b120d7062a493f98d203", 179 }, 180 { 181 crypto::SymmetricKey::HMAC_SHA1, 182 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 183 "pass phrase equals block size", 184 1200, 185 160, 186 "139c30c0966bc32ba55fdbf212530ac9c5ec59f1", 187 }, 188 { 189 crypto::SymmetricKey::HMAC_SHA1, 190 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 191 "pass phrase exceeds block size", 192 1200, 193 160, 194 "9ccad6d468770cd51b10e6a68721be611a8b4d28", 195 }, 196 { 197 crypto::SymmetricKey::HMAC_SHA1, 198 "\360\235\204\236", /* g-clef (0xf09d849e) */ 199 "EXAMPLE.COMpianist", 200 50, 201 160, 202 "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0", 203 }, 204 205 // Regression tests for AES keys, derived from the Linux NSS implementation. 206 { 207 crypto::SymmetricKey::AES, 208 "A test password", 209 "saltsalt", 210 1, 211 256, 212 "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de", 213 }, 214 { 215 crypto::SymmetricKey::AES, 216 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 217 "pass phrase exceeds block size", 218 20, 219 256, 220 "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c", 221 }, 222 }; 223 224 INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest, 225 testing::ValuesIn(kTestVectors)); 226