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