1 /* 2 * Copyright (c) 1997, 2018, 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 26 package sun.security.provider; 27 28 import java.security.Key; 29 import java.security.PublicKey; 30 import java.security.PrivateKey; 31 import java.security.KeyFactorySpi; 32 import java.security.InvalidKeyException; 33 import java.security.interfaces.DSAParams; 34 import java.security.spec.DSAPublicKeySpec; 35 import java.security.spec.DSAPrivateKeySpec; 36 import java.security.spec.KeySpec; 37 import java.security.spec.InvalidKeySpecException; 38 import java.security.spec.X509EncodedKeySpec; 39 import java.security.spec.PKCS8EncodedKeySpec; 40 41 /** 42 * This class implements the DSA key factory of the Sun provider. 43 * 44 * @author Jan Luehe 45 * 46 * 47 * @since 1.2 48 */ 49 50 public class DSAKeyFactory extends KeyFactorySpi { 51 /** 52 * Generates a public key object from the provided key specification 53 * (key material). 54 * 55 * @param keySpec the specification (key material) of the public key 56 * 57 * @return the public key 58 * 59 * @exception InvalidKeySpecException if the given key specification 60 * is inappropriate for this key factory to produce a public key. 61 */ engineGeneratePublic(KeySpec keySpec)62 protected PublicKey engineGeneratePublic(KeySpec keySpec) 63 throws InvalidKeySpecException { 64 try { 65 if (keySpec instanceof DSAPublicKeySpec) { 66 DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec)keySpec; 67 return new DSAPublicKeyImpl(dsaPubKeySpec.getY(), 68 dsaPubKeySpec.getP(), 69 dsaPubKeySpec.getQ(), 70 dsaPubKeySpec.getG()); 71 } else if (keySpec instanceof X509EncodedKeySpec) { 72 return new DSAPublicKeyImpl 73 (((X509EncodedKeySpec)keySpec).getEncoded()); 74 } else { 75 throw new InvalidKeySpecException 76 ("Inappropriate key specification"); 77 } 78 } catch (InvalidKeyException e) { 79 throw new InvalidKeySpecException 80 ("Inappropriate key specification: " + e.getMessage()); 81 } 82 } 83 84 /** 85 * Generates a private key object from the provided key specification 86 * (key material). 87 * 88 * @param keySpec the specification (key material) of the private key 89 * 90 * @return the private key 91 * 92 * @exception InvalidKeySpecException if the given key specification 93 * is inappropriate for this key factory to produce a private key. 94 */ engineGeneratePrivate(KeySpec keySpec)95 protected PrivateKey engineGeneratePrivate(KeySpec keySpec) 96 throws InvalidKeySpecException { 97 try { 98 if (keySpec instanceof DSAPrivateKeySpec) { 99 DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec)keySpec; 100 return new DSAPrivateKey(dsaPrivKeySpec.getX(), 101 dsaPrivKeySpec.getP(), 102 dsaPrivKeySpec.getQ(), 103 dsaPrivKeySpec.getG()); 104 105 } else if (keySpec instanceof PKCS8EncodedKeySpec) { 106 return new DSAPrivateKey 107 (((PKCS8EncodedKeySpec)keySpec).getEncoded()); 108 109 } else { 110 throw new InvalidKeySpecException 111 ("Inappropriate key specification"); 112 } 113 } catch (InvalidKeyException e) { 114 throw new InvalidKeySpecException 115 ("Inappropriate key specification: " + e.getMessage()); 116 } 117 } 118 119 /** 120 * Returns a specification (key material) of the given key object 121 * in the requested format. 122 * 123 * @param key the key 124 * 125 * @param keySpec the requested format in which the key material shall be 126 * returned 127 * 128 * @return the underlying key specification (key material) in the 129 * requested format 130 * 131 * @exception InvalidKeySpecException if the requested key specification is 132 * inappropriate for the given key, or the given key cannot be processed 133 * (e.g., the given key has an unrecognized algorithm or format). 134 */ 135 protected <T extends KeySpec> engineGetKeySpec(Key key, Class<T> keySpec)136 T engineGetKeySpec(Key key, Class<T> keySpec) 137 throws InvalidKeySpecException { 138 139 DSAParams params; 140 141 try { 142 143 if (key instanceof java.security.interfaces.DSAPublicKey) { 144 145 // Determine valid key specs 146 Class<?> dsaPubKeySpec = Class.forName 147 ("java.security.spec.DSAPublicKeySpec"); 148 Class<?> x509KeySpec = Class.forName 149 ("java.security.spec.X509EncodedKeySpec"); 150 151 if (dsaPubKeySpec.isAssignableFrom(keySpec)) { 152 java.security.interfaces.DSAPublicKey dsaPubKey 153 = (java.security.interfaces.DSAPublicKey)key; 154 params = dsaPubKey.getParams(); 155 return keySpec.cast(new DSAPublicKeySpec(dsaPubKey.getY(), 156 params.getP(), 157 params.getQ(), 158 params.getG())); 159 160 } else if (x509KeySpec.isAssignableFrom(keySpec)) { 161 return keySpec.cast(new X509EncodedKeySpec(key.getEncoded())); 162 163 } else { 164 throw new InvalidKeySpecException 165 ("Inappropriate key specification"); 166 } 167 168 } else if (key instanceof java.security.interfaces.DSAPrivateKey) { 169 170 // Determine valid key specs 171 Class<?> dsaPrivKeySpec = Class.forName 172 ("java.security.spec.DSAPrivateKeySpec"); 173 Class<?> pkcs8KeySpec = Class.forName 174 ("java.security.spec.PKCS8EncodedKeySpec"); 175 176 if (dsaPrivKeySpec.isAssignableFrom(keySpec)) { 177 java.security.interfaces.DSAPrivateKey dsaPrivKey 178 = (java.security.interfaces.DSAPrivateKey)key; 179 params = dsaPrivKey.getParams(); 180 return keySpec.cast(new DSAPrivateKeySpec(dsaPrivKey.getX(), 181 params.getP(), 182 params.getQ(), 183 params.getG())); 184 185 } else if (pkcs8KeySpec.isAssignableFrom(keySpec)) { 186 return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded())); 187 188 } else { 189 throw new InvalidKeySpecException 190 ("Inappropriate key specification"); 191 } 192 193 } else { 194 throw new InvalidKeySpecException("Inappropriate key type"); 195 } 196 197 } catch (ClassNotFoundException e) { 198 throw new InvalidKeySpecException 199 ("Unsupported key specification: " + e.getMessage()); 200 } 201 } 202 203 /** 204 * Translates a key object, whose provider may be unknown or potentially 205 * untrusted, into a corresponding key object of this key factory. 206 * 207 * @param key the key whose provider is unknown or untrusted 208 * 209 * @return the translated key 210 * 211 * @exception InvalidKeyException if the given key cannot be processed by 212 * this key factory. 213 */ engineTranslateKey(Key key)214 protected Key engineTranslateKey(Key key) throws InvalidKeyException { 215 216 try { 217 218 if (key instanceof java.security.interfaces.DSAPublicKey) { 219 // Check if key originates from this factory 220 if (key instanceof sun.security.provider.DSAPublicKey) { 221 return key; 222 } 223 // Convert key to spec 224 DSAPublicKeySpec dsaPubKeySpec 225 = engineGetKeySpec(key, DSAPublicKeySpec.class); 226 // Create key from spec, and return it 227 return engineGeneratePublic(dsaPubKeySpec); 228 229 } else if (key instanceof java.security.interfaces.DSAPrivateKey) { 230 // Check if key originates from this factory 231 if (key instanceof sun.security.provider.DSAPrivateKey) { 232 return key; 233 } 234 // Convert key to spec 235 DSAPrivateKeySpec dsaPrivKeySpec 236 = engineGetKeySpec(key, DSAPrivateKeySpec.class); 237 // Create key from spec, and return it 238 return engineGeneratePrivate(dsaPrivKeySpec); 239 240 } else { 241 throw new InvalidKeyException("Wrong algorithm type"); 242 } 243 244 } catch (InvalidKeySpecException e) { 245 throw new InvalidKeyException("Cannot translate key: " 246 + e.getMessage()); 247 } 248 } 249 } 250