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