jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java
changeset 25859 3317bb8137f4
parent 10336 0bb1999251f8
child 37593 824750ada3d6
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 1997, 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 
       
    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.AccessController;
       
    34 import java.security.interfaces.DSAParams;
       
    35 import java.security.spec.DSAPublicKeySpec;
       
    36 import java.security.spec.DSAPrivateKeySpec;
       
    37 import java.security.spec.KeySpec;
       
    38 import java.security.spec.InvalidKeySpecException;
       
    39 import java.security.spec.X509EncodedKeySpec;
       
    40 import java.security.spec.PKCS8EncodedKeySpec;
       
    41 
       
    42 import sun.security.action.GetPropertyAction;
       
    43 
       
    44 /**
       
    45  * This class implements the DSA key factory of the Sun provider.
       
    46  *
       
    47  * @author Jan Luehe
       
    48  *
       
    49  *
       
    50  * @since 1.2
       
    51  */
       
    52 
       
    53 public class DSAKeyFactory extends KeyFactorySpi {
       
    54 
       
    55     // package private for DSAKeyPairGenerator
       
    56     static final boolean SERIAL_INTEROP;
       
    57     private static final String SERIAL_PROP = "sun.security.key.serial.interop";
       
    58 
       
    59     static {
       
    60 
       
    61         /**
       
    62          * Check to see if we need to maintain interoperability for serialized
       
    63          * keys between JDK 5.0 -> JDK 1.4.  In other words, determine whether
       
    64          * a key object serialized in JDK 5.0 must be deserializable in
       
    65          * JDK 1.4.
       
    66          *
       
    67          * If true, then we generate sun.security.provider.DSAPublicKey.
       
    68          * If false, then we generate sun.security.provider.DSAPublicKeyImpl.
       
    69          *
       
    70          * By default this is false.
       
    71          * This incompatibility was introduced by 4532506.
       
    72          */
       
    73         String prop = AccessController.doPrivileged
       
    74                 (new GetPropertyAction(SERIAL_PROP, null));
       
    75         SERIAL_INTEROP = "true".equalsIgnoreCase(prop);
       
    76     }
       
    77 
       
    78     /**
       
    79      * Generates a public key object from the provided key specification
       
    80      * (key material).
       
    81      *
       
    82      * @param keySpec the specification (key material) of the public key
       
    83      *
       
    84      * @return the public key
       
    85      *
       
    86      * @exception InvalidKeySpecException if the given key specification
       
    87      * is inappropriate for this key factory to produce a public key.
       
    88      */
       
    89     protected PublicKey engineGeneratePublic(KeySpec keySpec)
       
    90     throws InvalidKeySpecException {
       
    91         try {
       
    92             if (keySpec instanceof DSAPublicKeySpec) {
       
    93                 DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec)keySpec;
       
    94                 if (SERIAL_INTEROP) {
       
    95                     return new DSAPublicKey(dsaPubKeySpec.getY(),
       
    96                                         dsaPubKeySpec.getP(),
       
    97                                         dsaPubKeySpec.getQ(),
       
    98                                         dsaPubKeySpec.getG());
       
    99                 } else {
       
   100                     return new DSAPublicKeyImpl(dsaPubKeySpec.getY(),
       
   101                                         dsaPubKeySpec.getP(),
       
   102                                         dsaPubKeySpec.getQ(),
       
   103                                         dsaPubKeySpec.getG());
       
   104                 }
       
   105             } else if (keySpec instanceof X509EncodedKeySpec) {
       
   106                 if (SERIAL_INTEROP) {
       
   107                     return new DSAPublicKey
       
   108                         (((X509EncodedKeySpec)keySpec).getEncoded());
       
   109                 } else {
       
   110                     return new DSAPublicKeyImpl
       
   111                         (((X509EncodedKeySpec)keySpec).getEncoded());
       
   112                 }
       
   113             } else {
       
   114                 throw new InvalidKeySpecException
       
   115                     ("Inappropriate key specification");
       
   116             }
       
   117         } catch (InvalidKeyException e) {
       
   118             throw new InvalidKeySpecException
       
   119                 ("Inappropriate key specification: " + e.getMessage());
       
   120         }
       
   121     }
       
   122 
       
   123     /**
       
   124      * Generates a private key object from the provided key specification
       
   125      * (key material).
       
   126      *
       
   127      * @param keySpec the specification (key material) of the private key
       
   128      *
       
   129      * @return the private key
       
   130      *
       
   131      * @exception InvalidKeySpecException if the given key specification
       
   132      * is inappropriate for this key factory to produce a private key.
       
   133      */
       
   134     protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
       
   135     throws InvalidKeySpecException {
       
   136         try {
       
   137             if (keySpec instanceof DSAPrivateKeySpec) {
       
   138                 DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec)keySpec;
       
   139                 return new DSAPrivateKey(dsaPrivKeySpec.getX(),
       
   140                                          dsaPrivKeySpec.getP(),
       
   141                                          dsaPrivKeySpec.getQ(),
       
   142                                          dsaPrivKeySpec.getG());
       
   143 
       
   144             } else if (keySpec instanceof PKCS8EncodedKeySpec) {
       
   145                 return new DSAPrivateKey
       
   146                     (((PKCS8EncodedKeySpec)keySpec).getEncoded());
       
   147 
       
   148             } else {
       
   149                 throw new InvalidKeySpecException
       
   150                     ("Inappropriate key specification");
       
   151             }
       
   152         } catch (InvalidKeyException e) {
       
   153             throw new InvalidKeySpecException
       
   154                 ("Inappropriate key specification: " + e.getMessage());
       
   155         }
       
   156     }
       
   157 
       
   158     /**
       
   159      * Returns a specification (key material) of the given key object
       
   160      * in the requested format.
       
   161      *
       
   162      * @param key the key
       
   163      *
       
   164      * @param keySpec the requested format in which the key material shall be
       
   165      * returned
       
   166      *
       
   167      * @return the underlying key specification (key material) in the
       
   168      * requested format
       
   169      *
       
   170      * @exception InvalidKeySpecException if the requested key specification is
       
   171      * inappropriate for the given key, or the given key cannot be processed
       
   172      * (e.g., the given key has an unrecognized algorithm or format).
       
   173      */
       
   174     protected <T extends KeySpec>
       
   175         T engineGetKeySpec(Key key, Class<T> keySpec)
       
   176     throws InvalidKeySpecException {
       
   177 
       
   178         DSAParams params;
       
   179 
       
   180         try {
       
   181 
       
   182             if (key instanceof java.security.interfaces.DSAPublicKey) {
       
   183 
       
   184                 // Determine valid key specs
       
   185                 Class<?> dsaPubKeySpec = Class.forName
       
   186                     ("java.security.spec.DSAPublicKeySpec");
       
   187                 Class<?> x509KeySpec = Class.forName
       
   188                     ("java.security.spec.X509EncodedKeySpec");
       
   189 
       
   190                 if (dsaPubKeySpec.isAssignableFrom(keySpec)) {
       
   191                     java.security.interfaces.DSAPublicKey dsaPubKey
       
   192                         = (java.security.interfaces.DSAPublicKey)key;
       
   193                     params = dsaPubKey.getParams();
       
   194                     return keySpec.cast(new DSAPublicKeySpec(dsaPubKey.getY(),
       
   195                                                              params.getP(),
       
   196                                                              params.getQ(),
       
   197                                                              params.getG()));
       
   198 
       
   199                 } else if (x509KeySpec.isAssignableFrom(keySpec)) {
       
   200                     return keySpec.cast(new X509EncodedKeySpec(key.getEncoded()));
       
   201 
       
   202                 } else {
       
   203                     throw new InvalidKeySpecException
       
   204                         ("Inappropriate key specification");
       
   205                 }
       
   206 
       
   207             } else if (key instanceof java.security.interfaces.DSAPrivateKey) {
       
   208 
       
   209                 // Determine valid key specs
       
   210                 Class<?> dsaPrivKeySpec = Class.forName
       
   211                     ("java.security.spec.DSAPrivateKeySpec");
       
   212                 Class<?> pkcs8KeySpec = Class.forName
       
   213                     ("java.security.spec.PKCS8EncodedKeySpec");
       
   214 
       
   215                 if (dsaPrivKeySpec.isAssignableFrom(keySpec)) {
       
   216                     java.security.interfaces.DSAPrivateKey dsaPrivKey
       
   217                         = (java.security.interfaces.DSAPrivateKey)key;
       
   218                     params = dsaPrivKey.getParams();
       
   219                     return keySpec.cast(new DSAPrivateKeySpec(dsaPrivKey.getX(),
       
   220                                                               params.getP(),
       
   221                                                               params.getQ(),
       
   222                                                               params.getG()));
       
   223 
       
   224                 } else if (pkcs8KeySpec.isAssignableFrom(keySpec)) {
       
   225                     return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
       
   226 
       
   227                 } else {
       
   228                     throw new InvalidKeySpecException
       
   229                         ("Inappropriate key specification");
       
   230                 }
       
   231 
       
   232             } else {
       
   233                 throw new InvalidKeySpecException("Inappropriate key type");
       
   234             }
       
   235 
       
   236         } catch (ClassNotFoundException e) {
       
   237             throw new InvalidKeySpecException
       
   238                 ("Unsupported key specification: " + e.getMessage());
       
   239         }
       
   240     }
       
   241 
       
   242     /**
       
   243      * Translates a key object, whose provider may be unknown or potentially
       
   244      * untrusted, into a corresponding key object of this key factory.
       
   245      *
       
   246      * @param key the key whose provider is unknown or untrusted
       
   247      *
       
   248      * @return the translated key
       
   249      *
       
   250      * @exception InvalidKeyException if the given key cannot be processed by
       
   251      * this key factory.
       
   252      */
       
   253     protected Key engineTranslateKey(Key key) throws InvalidKeyException {
       
   254 
       
   255         try {
       
   256 
       
   257             if (key instanceof java.security.interfaces.DSAPublicKey) {
       
   258                 // Check if key originates from this factory
       
   259                 if (key instanceof sun.security.provider.DSAPublicKey) {
       
   260                     return key;
       
   261                 }
       
   262                 // Convert key to spec
       
   263                 DSAPublicKeySpec dsaPubKeySpec
       
   264                     = engineGetKeySpec(key, DSAPublicKeySpec.class);
       
   265                 // Create key from spec, and return it
       
   266                 return engineGeneratePublic(dsaPubKeySpec);
       
   267 
       
   268             } else if (key instanceof java.security.interfaces.DSAPrivateKey) {
       
   269                 // Check if key originates from this factory
       
   270                 if (key instanceof sun.security.provider.DSAPrivateKey) {
       
   271                     return key;
       
   272                 }
       
   273                 // Convert key to spec
       
   274                 DSAPrivateKeySpec dsaPrivKeySpec
       
   275                     = engineGetKeySpec(key, DSAPrivateKeySpec.class);
       
   276                 // Create key from spec, and return it
       
   277                 return engineGeneratePrivate(dsaPrivKeySpec);
       
   278 
       
   279             } else {
       
   280                 throw new InvalidKeyException("Wrong algorithm type");
       
   281             }
       
   282 
       
   283         } catch (InvalidKeySpecException e) {
       
   284             throw new InvalidKeyException("Cannot translate key: "
       
   285                                           + e.getMessage());
       
   286         }
       
   287     }
       
   288 }