org.kse.crypto.publickey.OpenSslPubUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.kse.crypto.publickey.OpenSslPubUtil.java

Source

/*
 * Copyright 2004 - 2013 Wayne Grant
 *           2013 - 2019 Kai Kramer
 *
 * This file is part of KeyStore Explorer.
 *
 * KeyStore Explorer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * KeyStore Explorer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with KeyStore Explorer.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kse.crypto.publickey;

import java.io.IOException;
import java.security.PublicKey;
import java.util.ResourceBundle;

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.kse.crypto.CryptoException;
import org.kse.utilities.pem.PemInfo;
import org.kse.utilities.pem.PemUtil;

// @formatter:off
/**
 * Provides utility methods relating to OpenSSL/SubjectPublicKeyInfo encoded public keys. The PKCS#1 RSA public key
 * format is not supported.
 *
 * <pre>
 * -----BEGIN PUBLIC KEY-----
 * ...
 * -----END PUBLIC KEY-----
 * </pre>
 *
 * <pre>
 * OpenSSL Public Key structure:
 *
 *     SubjectPublicKeyInfo ::= ASN1Sequence {
 *         algorithm AlgorithmIdentifier,
 *         subjectPublicKey BIT STRING }
 *
 *     AlgorithmIdentifier ::= ASN1Sequence {
 *         algorithm OBJECT IDENTIFIER,
 *         parameters ANY DEFINED BY algorithm OPTIONAL }
 *
 *     Rsa-Parms ::= ASN1Null
 *
 *     Dss-Parms ::= ASN1Sequence {
 *         p ASN1Integer,
 *         q ASN1Integer,
 *         g ASN1Integer }
 *
 *     ECParameters ::= CHOICE {                      // RFC 5480
 *         namedCurve         OBJECT IDENTIFIER
 *         -- implicitCurve   NULL
 *         -- specifiedCurve  SpecifiedECDomain }
 *
 *     subjectPublicKey as DERBitString:
 *
 *     RSAPublicKey ::= ASN1Sequence {
 *         modulus ASN1Integer,
 *         publicExponent ASN1Integer}
 *
 *     DSAPublicKey ::= ASN1Integer
 *
 *     ECPoint ::= OCTET STRING
 * </pre>
 *
 */
// @formatter:on
public class OpenSslPubUtil {
    private static ResourceBundle res = ResourceBundle.getBundle("org/kse/crypto/publickey/resources");

    private static final String OPENSSL_PUB_PEM_TYPE = "PUBLIC KEY";

    private OpenSslPubUtil() {
    }

    /**
     * OpenSSL encode a public key.
     *
     * @return The encoding
     * @param publicKey
     *            The public key
     */
    public static byte[] get(PublicKey publicKey) {
        // The public key encoding is a DER-encoded subjectPublicKeyInfo structure - the OpenSSL format
        return publicKey.getEncoded();
    }

    /**
     * OpenSSL encode a public key and PEM the encoding.
     *
     * @return The PEM'd encoding
     * @param publicKey
     *            The public key
     */
    public static String getPem(PublicKey publicKey) {
        byte[] openSsl = get(publicKey);

        PemInfo pemInfo = new PemInfo(OPENSSL_PUB_PEM_TYPE, null, openSsl);
        String openSslPem = PemUtil.encode(pemInfo);

        return openSslPem;
    }

    /**
     * Load an unencrypted OpenSSL public key from the stream. The encoding of
     * the public key may be PEM or DER.
     *
     * @param pkData BA to load the unencrypted public key from
     * @return The public key
     * @throws CryptoException
     *             Problem encountered while loading the public key
     * @throws IOException
     *             An I/O error occurred
     */
    public static PublicKey load(byte[] pkData) throws CryptoException, IOException {

        // Check if stream is PEM encoded
        PemInfo pemInfo = PemUtil.decode(pkData);

        if (pemInfo != null) {
            // It is - get DER from PEM
            pkData = pemInfo.getContent();
        }

        try {
            // DER-encoded subjectPublicKeyInfo structure - the OpenSSL format
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pkData);
            return new JcaPEMKeyConverter().getPublicKey(publicKeyInfo);
        } catch (Exception ex) {
            throw new CryptoException(res.getString("NoLoadOpenSslPublicKey.exception.message"), ex);
        }
    }
}