1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage javax.crypto.spec; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.spec.KeySpec; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays; 226186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.EmptyArray; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The key specification for a <i>password based encryption</i> key. 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Password based encryption is described in <a 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * href="http://www.ietf.org/rfc/rfc2898.txt">PKCS #5</a>. 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class PBEKeySpec implements KeySpec { 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private char[] password; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final byte[] salt; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int iterationCount; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int keyLength; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new <code>PBEKeySpec</code> with the specified password. 39ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param password 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the password. 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public PBEKeySpec(char[] password) { 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (password == null) { 45693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes this.password = EmptyArray.CHAR; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.password = new char[password.length]; 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(password, 0, this.password, 0, password.length); 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project salt = null; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project iterationCount = 0; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = 0; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new <code>PBEKeySpec</code> with the specified password, salt, 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * iteration count and the desired length of the derived key. 58ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param password 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the password. 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param salt 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the salt. 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param iterationCount 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the iteration count. 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param keyLength 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the desired key length of the derived key, 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the salt is null. 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the salt is empty, iteration count is zero or negative or 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the key length is zero or negative. 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public PBEKeySpec(char[] password, byte[] salt, int iterationCount, 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int keyLength) { 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (salt == null) { 7680a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new NullPointerException("salt == null"); 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (salt.length == 0) { 7980a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalArgumentException("salt.length == 0"); 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (iterationCount <= 0) { 8280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalArgumentException("iterationCount <= 0"); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (keyLength <= 0) { 8580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalArgumentException("keyLength <= 0"); 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (password == null) { 89693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes this.password = EmptyArray.CHAR; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.password = new char[password.length]; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(password, 0, this.password, 0, password.length); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.salt = new byte[salt.length]; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(salt, 0, this.salt, 0, salt.length); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.iterationCount = iterationCount; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.keyLength = keyLength; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new <code>PBEKeySpec</code> with the specified password, salt 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and iteration count. 103ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param password 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the password. 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param salt 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the salt. 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param iterationCount 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the iteration count. 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if salt is null. 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the salt is empty or iteration count is zero or negative. 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public PBEKeySpec(char[] password, byte[] salt, int iterationCount) { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (salt == null) { 11780a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new NullPointerException("salt == null"); 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (salt.length == 0) { 12080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalArgumentException("salt.length == 0"); 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (iterationCount <= 0) { 12380a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalArgumentException("iterationCount <= 0"); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (password == null) { 127693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes this.password = EmptyArray.CHAR; 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.password = new char[password.length]; 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(password, 0, this.password, 0, password.length); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.salt = new byte[salt.length]; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(salt, 0, this.salt, 0, salt.length); 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.iterationCount = iterationCount; 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.keyLength = 0; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Clears the password by overwriting it. 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final void clearPassword() { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Arrays.fill(password, '?'); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project password = null; 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a copy of the password of this key specification. 148ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a copy of the password of this key specification. 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the password has been cleared before. 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final char[] getPassword() { 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (password == null) { 15580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes throw new IllegalStateException("The password has been cleared"); 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char[] result = new char[password.length]; 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(password, 0, result, 0, password.length); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a copy of the salt of this key specification. 164ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a copy of the salt of this key specification or null if none is 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final byte[] getSalt() { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (salt == null) { 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] result = new byte[salt.length]; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(salt, 0, result, 0, salt.length); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the iteration count of this key specification. 179ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the iteration count of this key specification. 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getIterationCount() { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return iterationCount; 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the desired key length of the derived key. 188ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the desired key length of the derived key. 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getKeyLength() { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return keyLength; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 195