alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (PKCS10.java)

This example Java source code file (PKCS10.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

algorithmid, certificate, deroutputstream, dervalue, illegalargumentexception, ioexception, math, nosuchalgorithmexception, pkcs, pkcs10, pkcs10attributes, publickey, request, security, signatureexception, util, x500name

The PKCS10.java Java example source code

/*
 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package sun.security.pkcs10;

import java.io.PrintStream;
import java.io.IOException;
import java.math.BigInteger;

import java.security.cert.CertificateException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.PublicKey;

import java.util.Base64;

import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X509Key;
import sun.security.x509.X500Name;

/**
 * A PKCS #10 certificate request is created and sent to a Certificate
 * Authority, which then creates an X.509 certificate and returns it to
 * the entity that requested it. A certificate request basically consists
 * of the subject's X.500 name, public key, and optionally some attributes,
 * signed using the corresponding private key.
 *
 * The ASN.1 syntax for a Certification Request is:
 * <pre>
 * CertificationRequest ::= SEQUENCE {
 *    certificationRequestInfo CertificationRequestInfo,
 *    signatureAlgorithm       SignatureAlgorithmIdentifier,
 *    signature                Signature
 *  }
 *
 * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
 * Signature ::= BIT STRING
 *
 * CertificationRequestInfo ::= SEQUENCE {
 *    version                 Version,
 *    subject                 Name,
 *    subjectPublicKeyInfo    SubjectPublicKeyInfo,
 *    attributes [0] IMPLICIT Attributes
 * }
 * Attributes ::= SET OF Attribute
 * </pre>
 *
 * @author David Brownell
 * @author Amit Kapoor
 * @author Hemma Prafullchandra
 */
public class PKCS10 {
    /**
     * Constructs an unsigned PKCS #10 certificate request.  Before this
     * request may be used, it must be encoded and signed.  Then it
     * must be retrieved in some conventional format (e.g. string).
     *
     * @param publicKey the public key that should be placed
     *          into the certificate generated by the CA.
     */
    public PKCS10(PublicKey publicKey) {
        subjectPublicKeyInfo = publicKey;
        attributeSet = new PKCS10Attributes();
    }

    /**
     * Constructs an unsigned PKCS #10 certificate request.  Before this
     * request may be used, it must be encoded and signed.  Then it
     * must be retrieved in some conventional format (e.g. string).
     *
     * @param publicKey the public key that should be placed
     *          into the certificate generated by the CA.
     * @param attributes additonal set of PKCS10 attributes requested
     *          for in the certificate.
     */
    public PKCS10(PublicKey publicKey, PKCS10Attributes attributes) {
        subjectPublicKeyInfo = publicKey;
        attributeSet = attributes;
    }

    /**
     * Parses an encoded, signed PKCS #10 certificate request, verifying
     * the request's signature as it does so.  This constructor would
     * typically be used by a Certificate Authority, from which a new
     * certificate would then be constructed.
     *
     * @param data the DER-encoded PKCS #10 request.
     * @exception IOException for low level errors reading the data
     * @exception SignatureException when the signature is invalid
     * @exception NoSuchAlgorithmException when the signature
     *  algorithm is not supported in this environment
     */
    public PKCS10(byte[] data)
    throws IOException, SignatureException, NoSuchAlgorithmException {
        DerInputStream  in;
        DerValue[]      seq;
        AlgorithmId     id;
        byte[]          sigData;
        Signature       sig;

        encoded = data;

        //
        // Outer sequence:  request, signature algorithm, signature.
        // Parse, and prepare to verify later.
        //
        in = new DerInputStream(data);
        seq = in.getSequence(3);

        if (seq.length != 3)
            throw new IllegalArgumentException("not a PKCS #10 request");

        data = seq[0].toByteArray();            // reusing this variable
        id = AlgorithmId.parse(seq[1]);
        sigData = seq[2].getBitString();

        //
        // Inner sequence:  version, name, key, attributes
        //
        BigInteger      serial;
        DerValue        val;

        serial = seq[0].data.getBigInteger();
        if (!serial.equals(BigInteger.ZERO))
            throw new IllegalArgumentException("not PKCS #10 v1");

        subject = new X500Name(seq[0].data);
        subjectPublicKeyInfo = X509Key.parse(seq[0].data.getDerValue());

        // Cope with a somewhat common illegal PKCS #10 format
        if (seq[0].data.available() != 0)
            attributeSet = new PKCS10Attributes(seq[0].data);
        else
            attributeSet = new PKCS10Attributes();

        if (seq[0].data.available() != 0)
            throw new IllegalArgumentException("illegal PKCS #10 data");

        //
        // OK, we parsed it all ... validate the signature using the
        // key and signature algorithm we found.
        //
        try {
            sig = Signature.getInstance(id.getName());
            sig.initVerify(subjectPublicKeyInfo);
            sig.update(data);
            if (!sig.verify(sigData))
                throw new SignatureException("Invalid PKCS #10 signature");
        } catch (InvalidKeyException e) {
            throw new SignatureException("invalid key");
        }
    }

    /**
     * Create the signed certificate request.  This will later be
     * retrieved in either string or binary format.
     *
     * @param subject identifies the signer (by X.500 name).
     * @param signature private key and signing algorithm to use.
     * @exception IOException on errors.
     * @exception CertificateException on certificate handling errors.
     * @exception SignatureException on signature handling errors.
     */
    public void encodeAndSign(X500Name subject, Signature signature)
    throws CertificateException, IOException, SignatureException {
        DerOutputStream out, scratch;
        byte[]          certificateRequestInfo;
        byte[]          sig;

        if (encoded != null)
            throw new SignatureException("request is already signed");

        this.subject = subject;

        /*
         * Encode cert request info, wrap in a sequence for signing
         */
        scratch = new DerOutputStream();
        scratch.putInteger(BigInteger.ZERO);            // PKCS #10 v1.0
        subject.encode(scratch);                        // X.500 name
        scratch.write(subjectPublicKeyInfo.getEncoded()); // public key
        attributeSet.encode(scratch);

        out = new DerOutputStream();
        out.write(DerValue.tag_Sequence, scratch);      // wrap it!
        certificateRequestInfo = out.toByteArray();
        scratch = out;

        /*
         * Sign it ...
         */
        signature.update(certificateRequestInfo, 0,
                certificateRequestInfo.length);
        sig = signature.sign();

        /*
         * Build guts of SIGNED macro
         */
        AlgorithmId algId = null;
        try {
            algId = AlgorithmId.get(signature.getAlgorithm());
        } catch (NoSuchAlgorithmException nsae) {
            throw new SignatureException(nsae);
        }
        algId.encode(scratch);     // sig algorithm
        scratch.putBitString(sig);                      // sig

        /*
         * Wrap those guts in a sequence
         */
        out = new DerOutputStream();
        out.write(DerValue.tag_Sequence, scratch);
        encoded = out.toByteArray();
    }

    /**
     * Returns the subject's name.
     */
    public X500Name getSubjectName() { return subject; }

    /**
     * Returns the subject's public key.
     */
    public PublicKey getSubjectPublicKeyInfo()
        { return subjectPublicKeyInfo; }

    /**
     * Returns the additional attributes requested.
     */
    public PKCS10Attributes getAttributes()
        { return attributeSet; }

    /**
     * Returns the encoded and signed certificate request as a
     * DER-encoded byte array.
     *
     * @return the certificate request, or null if encodeAndSign()
     *          has not yet been called.
     */
    public byte[] getEncoded() {
        if (encoded != null)
            return encoded.clone();
        else
            return null;
    }

    /**
     * Prints an E-Mailable version of the certificate request on the print
     * stream passed.  The format is a common base64 encoded one, supported
     * by most Certificate Authorities because Netscape web servers have
     * used this for some time.  Some certificate authorities expect some
     * more information, in particular contact information for the web
     * server administrator.
     *
     * @param out the print stream where the certificate request
     *  will be printed.
     * @exception IOException when an output operation failed
     * @exception SignatureException when the certificate request was
     *  not yet signed.
     */
    public void print(PrintStream out)
    throws IOException, SignatureException {
        if (encoded == null)
            throw new SignatureException("Cert request was not signed");


        out.println("-----BEGIN NEW CERTIFICATE REQUEST-----");
        out.println(Base64.getMimeEncoder().encodeToString(encoded));
        out.println("-----END NEW CERTIFICATE REQUEST-----");
    }

    /**
     * Provides a short description of this request.
     */
    public String toString() {
        return "[PKCS #10 certificate request:\n"
            + subjectPublicKeyInfo.toString()
            + " subject: <" + subject + ">" + "\n"
            + " attributes: " + attributeSet.toString()
            + "\n]";
    }

    /**
     * Compares this object for equality with the specified
     * object. If the <code>other object is an
     * <code>instanceof PKCS10, then
     * its encoded form is retrieved and compared with the
     * encoded form of this certificate request.
     *
     * @param other the object to test for equality with this object.
     * @return true iff the encoded forms of the two certificate
     * requests match, false otherwise.
     */
    public boolean equals(Object other) {
        if (this == other)
            return true;
        if (!(other instanceof PKCS10))
            return false;
        if (encoded == null) // not signed yet
            return false;
        byte[] otherEncoded = ((PKCS10)other).getEncoded();
        if (otherEncoded == null)
            return false;

        return java.util.Arrays.equals(encoded, otherEncoded);
    }

    /**
     * Returns a hashcode value for this certificate request from its
     * encoded form.
     *
     * @return the hashcode value.
     */
    public int hashCode() {
        int     retval = 0;
        if (encoded != null)
            for (int i = 1; i < encoded.length; i++)
             retval += encoded[i] * i;
        return(retval);
    }

    private X500Name            subject;
    private PublicKey           subjectPublicKeyInfo;
    private PKCS10Attributes    attributeSet;
    private byte[]              encoded;        // signed
}

Other Java examples (source code examples)

Here is a short list of links related to this Java PKCS10.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.