001    /*
002     * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/trunk/src/java/org/apache/commons/ssl/Certificates.java $
003     * $Revision: 121 $
004     * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005     *
006     * ====================================================================
007     * Licensed to the Apache Software Foundation (ASF) under one
008     * or more contributor license agreements.  See the NOTICE file
009     * distributed with this work for additional information
010     * regarding copyright ownership.  The ASF licenses this file
011     * to you under the Apache License, Version 2.0 (the
012     * "License"); you may not use this file except in compliance
013     * with the License.  You may obtain a copy of the License at
014     *
015     *   http://www.apache.org/licenses/LICENSE-2.0
016     *
017     * Unless required by applicable law or agreed to in writing,
018     * software distributed under the License is distributed on an
019     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020     * KIND, either express or implied.  See the License for the
021     * specific language governing permissions and limitations
022     * under the License.
023     * ====================================================================
024     *
025     * This software consists of voluntary contributions made by many
026     * individuals on behalf of the Apache Software Foundation.  For more
027     * information on the Apache Software Foundation, please see
028     * <http://www.apache.org/>.
029     *
030     */
031    package org.apache.commons.ssl.util;
032    
033    import java.math.BigInteger;
034    import java.security.GeneralSecurityException;
035    import java.security.KeyException;
036    import java.security.KeyFactory;
037    import java.security.PrivateKey;
038    import java.security.PublicKey;
039    import java.security.interfaces.DSAParams;
040    import java.security.interfaces.DSAPrivateKey;
041    import java.security.interfaces.RSAPrivateCrtKey;
042    import java.security.spec.DSAPublicKeySpec;
043    import java.security.spec.RSAPublicKeySpec;
044    
045    /**
046     * Utility class for deriving a public key from a given private key.
047     *
048     * @author Chad La Joie <lajoie OF georgetown.edu>
049     * @since November 14th, 2007
050     */
051    public class PublicKeyDeriver {
052    
053        /**
054         * Utility method for deriving a public key from a given private key.
055         *
056         * @param key private key for which we need a public key (DSA or RSA).
057         * @return the corresponding public key
058         * @throws GeneralSecurityException if it didn't work
059         */
060        public static PublicKey derivePublicKey(PrivateKey key) throws GeneralSecurityException {
061            if (key instanceof DSAPrivateKey) {
062                DSAPrivateKey dsaKey = (DSAPrivateKey) key;
063                DSAParams keyParams = dsaKey.getParams();
064                BigInteger g = keyParams.getG();
065                BigInteger p = keyParams.getP();
066                BigInteger q = keyParams.getQ();
067                BigInteger x = dsaKey.getX();
068                BigInteger y = q.modPow(x, p);
069                DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, p, q, g);
070                return KeyFactory.getInstance("DSA").generatePublic(keySpec);
071            } else if (key instanceof RSAPrivateCrtKey) {
072                RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
073                BigInteger modulus = rsaKey.getModulus();
074                BigInteger exponent = rsaKey.getPublicExponent();
075                RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
076                return KeyFactory.getInstance("RSA").generatePublic(keySpec);
077            } else {
078                throw new KeyException("Private key was not a DSA or RSA key");
079            }
080        }
081    }
082