1915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom/* 2915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * Copyright (C) 2010 The Android Open Source Project 3915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 4915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * you may not use this file except in compliance with the License. 6915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * You may obtain a copy of the License at 7915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 8915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 10915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * See the License for the specific language governing permissions and 14915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * limitations under the License. 15915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom */ 16915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 17915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrompackage libcore.javax.crypto; 18915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 19915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport java.security.spec.InvalidKeySpecException; 20915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport java.security.spec.KeySpec; 21915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport java.util.Arrays; 22915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport javax.crypto.SecretKey; 23915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport javax.crypto.SecretKeyFactory; 24915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport javax.crypto.spec.PBEKeySpec; 25915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstromimport junit.framework.TestCase; 263f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luhimport libcore.java.security.StandardNames; 27915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 28915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrompublic class SecretKeyFactoryTest extends TestCase { 29915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 30915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom private static final char[] PASSWORD = "google".toCharArray(); 31915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom /** 32915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * Salts should be random to reduce effectiveness of dictionary 33915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * attacks, but need not be kept secret from attackers. For more 34915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * information, see http://en.wikipedia.org/wiki/Salt_(cryptography) 35915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom */ 36915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom private static final byte[] SALT = {0, 1, 2, 3, 4, 5, 6, 7}; 37915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom /** 38915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * The number of iterations should be higher for production 39915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * strength protection. The tolerable value may vary from device 40915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * to device, but 8192 should be acceptable for PBKDF2 on a Nexus One. 41915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom */ 42915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom private static final int ITERATIONS = 1024; 43915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom private static final int KEY_LENGTH = 128; 44915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 45915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom public void test_PBKDF2_required_parameters() throws Exception { 46915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 47915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 48915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom // PBEKeySpec validates arguments most to be non-null, non-empty, postive, etc. 49915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom // Focus on insufficient PBEKeySpecs 50915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 51915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom // PBEKeySpecs password only constructor 52915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 53915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(null); 54915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 55915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 56915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 57915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 58915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 59915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(new char[0]); 60915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 61915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 62915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 63915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 64915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 65915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(PASSWORD); 66915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 67915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 68915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 69915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 70915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 71915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 72915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom // PBEKeySpecs constructor without key length 73915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 74915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(null, SALT, ITERATIONS); 75915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 76915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 77915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 78915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 79915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 80915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(new char[0], SALT, ITERATIONS); 81915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 82915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 83915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 84915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 85915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 86915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(PASSWORD, SALT, ITERATIONS); 87915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 88915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 89915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (InvalidKeySpecException expected) { 90915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 91915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 92915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 93915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(null, SALT, ITERATIONS, KEY_LENGTH); 94915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 95915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 96915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (IllegalArgumentException expected) { 97915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 98915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 99915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom try { 100915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(new char[0], SALT, ITERATIONS, KEY_LENGTH); 101915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 102915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom fail(); 103915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } catch (IllegalArgumentException expected) { 104915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 105915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 106915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(PASSWORD, SALT, ITERATIONS, KEY_LENGTH); 107915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom factory.generateSecret(ks); 108915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 109915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 110915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom public void test_PBKDF2_b3059950() throws Exception { 1113f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] expected = new byte[] { 112915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x70, (byte)0x74, (byte)0xdb, (byte)0x72, 113915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x35, (byte)0xd4, (byte)0x11, (byte)0x68, 114915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x83, (byte)0x7c, (byte)0x14, (byte)0x1f, 115915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0xf6, (byte)0x4a, (byte)0xb0, (byte)0x54 1163f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh }; 1173f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_UTF8(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected); 1183f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_8BIT(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected); 119915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 120915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 121915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom /** 122915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 64-bit Test vector from RFC 3211 123915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 124915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * See also org.bouncycastle.crypto.test.PKCS5Test 125915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom */ 126915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom public void test_PBKDF2_rfc3211_64() throws Exception { 127915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom char[] password = "password".toCharArray(); 128915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom byte[] salt = new byte[] { 129915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, 130915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x78, (byte)0x56, (byte)0x34, (byte)0x12 131915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom }; 132915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom int iterations = 5; 133915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom int keyLength = 64; 134915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom byte[] expected = new byte[] { 135915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0xD1, (byte)0xDA, (byte)0xA7, (byte)0x86, 136915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x15, (byte)0xF2, (byte)0x87, (byte)0xE6 137915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom }; 1383f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected); 1393f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected); 140915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 141915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 142915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom /** 143915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 192-bit Test vector from RFC 3211 144915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * 145915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom * See also org.bouncycastle.crypto.test.PKCS5Test 146915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom */ 147915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom public void test_PBKDF2_rfc3211_192() throws Exception { 148915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom char[] password = ("All n-entities must communicate with other " 149915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom + "n-entities via n-1 entiteeheehees").toCharArray(); 150915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom byte[] salt = new byte[] { 151915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, 152915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x78, (byte)0x56, (byte)0x34, (byte)0x12 153915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom }; 154915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom int iterations = 500; 155915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom int keyLength = 192; 156915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom byte[] expected = new byte[] { 157915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x6a, (byte)0x89, (byte)0x70, (byte)0xbf, (byte)0x68, (byte)0xc9, 158915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x2c, (byte)0xae, (byte)0xa8, (byte)0x4a, (byte)0x8d, (byte)0xf2, 159915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x85, (byte)0x10, (byte)0x85, (byte)0x86, (byte)0x07, (byte)0x12, 160915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom (byte)0x63, (byte)0x80, (byte)0xcc, (byte)0x47, (byte)0xab, (byte)0x2d 161915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom }; 1623f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected); 1633f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected); 1643f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh } 1653f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh 1663f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh /** 1673f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh * Unicode Test vector for b/8312059. 1683f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh * 1693f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh * See also https://code.google.com/p/android/issues/detail?id=40578 1703f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh */ 1713f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh public void test_PBKDF2_b8312059() throws Exception { 1723f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh 1733f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh char[] password = "\u0141\u0142".toCharArray(); 1743f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] salt = "salt".getBytes(); 1753f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh int iterations = 4096; 1763f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh int keyLength = 160; 1773f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] expected_utf8 = new byte[] { 1783f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x4c, (byte)0xe0, (byte)0x6a, (byte)0xb8, (byte)0x48, (byte)0x04, 1793f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0xb7, (byte)0xe7, (byte)0x72, (byte)0xf2, (byte)0xaf, (byte)0x5e, 1803f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x54, (byte)0xe9, (byte)0x03, (byte)0xad, (byte)0x59, (byte)0x64, 1813f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x8b, (byte)0xab 1823f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh }; 1833f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] expected_8bit = new byte[] { 1843f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x6e, (byte)0x43, (byte)0xe0, (byte)0x18, (byte)0xc5, (byte)0x50, 1853f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x0d, (byte)0xa7, (byte)0xfe, (byte)0x7a, (byte)0x44, (byte)0x4d, 1863f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x99, (byte)0x5d, (byte)0x8c, (byte)0xae, (byte)0xc1, (byte)0xc9, 1873f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh (byte)0x17, (byte)0xce 1883f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh }; 1893f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected_utf8); 1903f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected_8bit); 1913f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh } 1923f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh 1933f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh private void test_PBKDF2_8BIT(char[] password, byte[] salt, int iterations, int keyLength, 1943f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] expected) throws Exception { 1953f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh if (!StandardNames.IS_RI) { 1963f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8bit"); 1973f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength); 1983f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh SecretKey key = factory.generateSecret(ks); 1993f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh assertTrue(Arrays.equals(expected, key.getEncoded())); 2003f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh } 2013f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh 202915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 203915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 2043f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh private void test_PBKDF2_UTF8(char[] password, byte[] salt, int iterations, int keyLength, 2053f410d3b2d68c77a2a84629b47c29226c235f57dWilliam Luh byte[] expected) throws Exception { 206915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 207915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength); 208915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom SecretKey key = factory.generateSecret(ks); 209915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom assertTrue(Arrays.equals(expected, key.getEncoded())); 210915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom 211915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom } 212915789995fc136049c13c8b0354e2f7009b653e4Brian Carlstrom} 213