Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.javax.crypto;
     18 
     19 import java.security.spec.InvalidKeySpecException;
     20 import java.security.spec.KeySpec;
     21 import java.util.Arrays;
     22 import javax.crypto.SecretKey;
     23 import javax.crypto.SecretKeyFactory;
     24 import javax.crypto.spec.PBEKeySpec;
     25 import junit.framework.TestCase;
     26 
     27 public class SecretKeyFactoryTest extends TestCase {
     28 
     29     private static final char[] PASSWORD = "google".toCharArray();
     30     /**
     31      * Salts should be random to reduce effectiveness of dictionary
     32      * attacks, but need not be kept secret from attackers. For more
     33      * information, see http://en.wikipedia.org/wiki/Salt_(cryptography)
     34      */
     35     private static final byte[] SALT = {0, 1, 2, 3, 4, 5, 6, 7};
     36     /**
     37      * The number of iterations should be higher for production
     38      * strength protection. The tolerable value may vary from device
     39      * to device, but 8192 should be acceptable for PBKDF2 on a Nexus One.
     40      */
     41     private static final int ITERATIONS = 1024;
     42     private static final int KEY_LENGTH = 128;
     43 
     44     public void test_PBKDF2_required_parameters() throws Exception {
     45         SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
     46 
     47         // PBEKeySpec validates arguments most to be non-null, non-empty, postive, etc.
     48         // Focus on insufficient PBEKeySpecs
     49 
     50         // PBEKeySpecs password only constructor
     51         try {
     52             KeySpec ks = new PBEKeySpec(null);
     53             factory.generateSecret(ks);
     54             fail();
     55         } catch (InvalidKeySpecException expected) {
     56         }
     57         try {
     58             KeySpec ks = new PBEKeySpec(new char[0]);
     59             factory.generateSecret(ks);
     60             fail();
     61         } catch (InvalidKeySpecException expected) {
     62         }
     63         try {
     64             KeySpec ks = new PBEKeySpec(PASSWORD);
     65             factory.generateSecret(ks);
     66             fail();
     67         } catch (InvalidKeySpecException expected) {
     68         }
     69 
     70 
     71         // PBEKeySpecs constructor without key length
     72         try {
     73             KeySpec ks = new PBEKeySpec(null, SALT, ITERATIONS);
     74             factory.generateSecret(ks);
     75             fail();
     76         } catch (InvalidKeySpecException expected) {
     77         }
     78         try {
     79             KeySpec ks = new PBEKeySpec(new char[0], SALT, ITERATIONS);
     80             factory.generateSecret(ks);
     81             fail();
     82         } catch (InvalidKeySpecException expected) {
     83         }
     84         try {
     85             KeySpec ks = new PBEKeySpec(PASSWORD, SALT, ITERATIONS);
     86             factory.generateSecret(ks);
     87             fail();
     88         } catch (InvalidKeySpecException expected) {
     89         }
     90 
     91         try {
     92             KeySpec ks = new PBEKeySpec(null, SALT, ITERATIONS, KEY_LENGTH);
     93             factory.generateSecret(ks);
     94             fail();
     95         } catch (IllegalArgumentException expected) {
     96         }
     97 
     98         try {
     99             KeySpec ks = new PBEKeySpec(new char[0], SALT, ITERATIONS, KEY_LENGTH);
    100             factory.generateSecret(ks);
    101             fail();
    102         } catch (IllegalArgumentException expected) {
    103         }
    104 
    105         KeySpec ks = new PBEKeySpec(PASSWORD, SALT, ITERATIONS, KEY_LENGTH);
    106         factory.generateSecret(ks);
    107     }
    108 
    109     public void test_PBKDF2_b3059950() throws Exception {
    110         test_PBKDF2(PASSWORD, SALT, ITERATIONS, KEY_LENGTH,
    111                     new byte[] {
    112                         (byte)0x70, (byte)0x74, (byte)0xdb, (byte)0x72,
    113                         (byte)0x35, (byte)0xd4, (byte)0x11, (byte)0x68,
    114                         (byte)0x83, (byte)0x7c, (byte)0x14, (byte)0x1f,
    115                         (byte)0xf6, (byte)0x4a, (byte)0xb0, (byte)0x54
    116                     });
    117     }
    118 
    119     /**
    120      * 64-bit Test vector from RFC 3211
    121      *
    122      * See also org.bouncycastle.crypto.test.PKCS5Test
    123      */
    124     public void test_PBKDF2_rfc3211_64() throws Exception {
    125         char[] password = "password".toCharArray();
    126         byte[] salt = new byte[] {
    127             (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78,
    128             (byte)0x78, (byte)0x56, (byte)0x34, (byte)0x12
    129         };
    130         int iterations = 5;
    131         int keyLength = 64;
    132         byte[] expected = new byte[] {
    133             (byte)0xD1, (byte)0xDA, (byte)0xA7, (byte)0x86,
    134             (byte)0x15, (byte)0xF2, (byte)0x87, (byte)0xE6
    135         };
    136         test_PBKDF2(password, salt, iterations, keyLength, expected);
    137     }
    138 
    139     /**
    140      * 192-bit Test vector from RFC 3211
    141      *
    142      * See also org.bouncycastle.crypto.test.PKCS5Test
    143      */
    144     public void test_PBKDF2_rfc3211_192() throws Exception {
    145         char[] password = ("All n-entities must communicate with other "
    146                            + "n-entities via n-1 entiteeheehees").toCharArray();
    147         byte[] salt = new byte[] {
    148             (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78,
    149             (byte)0x78, (byte)0x56, (byte)0x34, (byte)0x12
    150         };
    151         int iterations = 500;
    152         int keyLength = 192;
    153         byte[] expected = new byte[] {
    154             (byte)0x6a, (byte)0x89, (byte)0x70, (byte)0xbf, (byte)0x68, (byte)0xc9,
    155             (byte)0x2c, (byte)0xae, (byte)0xa8, (byte)0x4a, (byte)0x8d, (byte)0xf2,
    156             (byte)0x85, (byte)0x10, (byte)0x85, (byte)0x86, (byte)0x07, (byte)0x12,
    157             (byte)0x63, (byte)0x80, (byte)0xcc, (byte)0x47, (byte)0xab, (byte)0x2d
    158         };
    159         test_PBKDF2(password, salt, iterations, keyLength, expected);
    160     }
    161 
    162     private void test_PBKDF2(char[] password, byte[] salt, int iterations, int keyLength,
    163                              byte[] expected) throws Exception {
    164         SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    165         KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength);
    166         SecretKey key = factory.generateSecret(ks);
    167         assertTrue(Arrays.equals(expected, key.getEncoded()));
    168 
    169     }
    170 }
    171