1/* 2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.crypto.provider; 27 28import java.security.InvalidKeyException; 29import java.security.spec.KeySpec; 30import java.security.spec.InvalidKeySpecException; 31import javax.crypto.SecretKey; 32import javax.crypto.SecretKeyFactorySpi; 33import javax.crypto.spec.PBEKeySpec; 34 35/** 36 * This class implements a key factory for PBE keys derived using 37 * PBKDF2 with HmacSHA1 psuedo random function(PRF) as defined in 38 * PKCS#5 v2.0. 39 * 40 * @author Valerie Peng 41 * 42 */ 43public final class PBKDF2HmacSHA1Factory extends SecretKeyFactorySpi { 44 45 /** 46 * Empty constructor 47 */ 48 public PBKDF2HmacSHA1Factory() { 49 } 50 51 /** 52 * Generates a <code>SecretKey</code> object from the provided key 53 * specification (key material). 54 * 55 * @param keySpec the specification (key material) of the secret key 56 * 57 * @return the secret key 58 * 59 * @exception InvalidKeySpecException if the given key specification 60 * is inappropriate for this key factory to produce a public key. 61 */ 62 protected SecretKey engineGenerateSecret(KeySpec keySpec) 63 throws InvalidKeySpecException 64 { 65 if (!(keySpec instanceof PBEKeySpec)) { 66 throw new InvalidKeySpecException("Invalid key spec"); 67 } 68 PBEKeySpec ks = (PBEKeySpec) keySpec; 69 return new PBKDF2KeyImpl(ks, "HmacSHA1"); 70 } 71 72 /** 73 * Returns a specification (key material) of the given key 74 * in the requested format. 75 * 76 * @param key the key 77 * 78 * @param keySpecCl the requested format in which the key material shall be 79 * returned 80 * 81 * @return the underlying key specification (key material) in the 82 * requested format 83 * 84 * @exception InvalidKeySpecException if the requested key 85 * specification is inappropriate for the given key, or the 86 * given key cannot be processed (e.g., the given key has an 87 * unrecognized algorithm or format). 88 */ 89 protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpecCl) 90 throws InvalidKeySpecException { 91 if (key instanceof javax.crypto.interfaces.PBEKey) { 92 // Check if requested key spec is amongst the valid ones 93 if ((keySpecCl != null) 94 && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { 95 javax.crypto.interfaces.PBEKey pKey = 96 (javax.crypto.interfaces.PBEKey) key; 97 return new PBEKeySpec 98 (pKey.getPassword(), pKey.getSalt(), 99 pKey.getIterationCount(), pKey.getEncoded().length*8); 100 } else { 101 throw new InvalidKeySpecException("Invalid key spec"); 102 } 103 } else { 104 throw new InvalidKeySpecException("Invalid key " + 105 "format/algorithm"); 106 } 107 } 108 109 /** 110 * Translates a <code>SecretKey</code> object, whose provider may be 111 * unknown or potentially untrusted, into a corresponding 112 * <code>SecretKey</code> object of this key factory. 113 * 114 * @param key the key whose provider is unknown or untrusted 115 * 116 * @return the translated key 117 * 118 * @exception InvalidKeyException if the given key cannot be processed by 119 * this key factory. 120 */ 121 protected SecretKey engineTranslateKey(SecretKey key) 122 throws InvalidKeyException { 123 if ((key != null) && 124 (key.getAlgorithm().equalsIgnoreCase("PBKDF2WithHmacSHA1")) && 125 (key.getFormat().equalsIgnoreCase("RAW"))) { 126 127 // Check if key originates from this factory 128 if (key instanceof com.sun.crypto.provider.PBKDF2KeyImpl) { 129 return key; 130 } 131 // Check if key implements the PBEKey 132 if (key instanceof javax.crypto.interfaces.PBEKey) { 133 javax.crypto.interfaces.PBEKey pKey = 134 (javax.crypto.interfaces.PBEKey) key; 135 try { 136 PBEKeySpec spec = 137 new PBEKeySpec(pKey.getPassword(), 138 pKey.getSalt(), 139 pKey.getIterationCount(), 140 pKey.getEncoded().length*8); 141 return new PBKDF2KeyImpl(spec, "HmacSHA1"); 142 } catch (InvalidKeySpecException re) { 143 InvalidKeyException ike = new InvalidKeyException 144 ("Invalid key component(s)"); 145 ike.initCause(re); 146 throw ike; 147 } 148 } 149 } 150 throw new InvalidKeyException("Invalid key format/algorithm"); 151 } 152} 153