1/* 2 * Copyright (c) 2005, 2012, 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/HmacSHA224/HmacSHA256/HmacSHA384/HmacSHA512 38 * pseudo random function (PRF) as defined in PKCS#5 v2.1. 39 * 40 * @author Valerie Peng 41 * 42 */ 43abstract class PBKDF2Core extends SecretKeyFactorySpi { 44 45 private final String prfAlgo; 46 47 PBKDF2Core(String prfAlgo) { 48 this.prfAlgo = prfAlgo; 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, prfAlgo); 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 keySpec 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("PBKDF2With" + prfAlgo)) && 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, prfAlgo); 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 public static final class HmacSHA1 extends PBKDF2Core { 154 public HmacSHA1() { 155 super("HmacSHA1"); 156 } 157 } 158 159 public static final class HmacSHA224 extends PBKDF2Core { 160 public HmacSHA224() { 161 super("HmacSHA224"); 162 } 163 } 164 165 public static final class HmacSHA256 extends PBKDF2Core { 166 public HmacSHA256() { 167 super("HmacSHA256"); 168 } 169 } 170 171 public static final class HmacSHA384 extends PBKDF2Core { 172 public HmacSHA384() { 173 super("HmacSHA384"); 174 } 175 } 176 177 public static final class HmacSHA512 extends PBKDF2Core { 178 public HmacSHA512() { 179 super("HmacSHA512"); 180 } 181 } 182} 183