com.vmware.identity.rest.core.util.CertificateHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.identity.rest.core.util.CertificateHelper.java

Source

/*
 *  Copyright (c) 2012-2015 VMware, Inc.  All Rights Reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not
 *  use this file except in compliance with the License.  You may obtain a copy
 *  of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, without
 *  warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED.  See the
 *  License for the specific language governing permissions and limitations
 *  under the License.
 */
package com.vmware.identity.rest.core.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.commons.codec.binary.Base64;

/**
 * The {@code CertificateHelper} class contains utilities for working with
 * {@code X509Certificates} and PEM-formatted encodings of {@code X509Certificates}.
 */
public class CertificateHelper {

    private static final String X509_CERT_TYPE = "X.509";
    private static final String FINGERPRINT_ALGORITHM = "SHA-1";
    private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
    private static final String END_CERT = "-----END CERTIFICATE-----";
    private static final int LINE_LENGTH = 57;
    private static final byte[] CHUNK_SEPARATOR = { '\n' };

    /**
     * Converts a PEM formatted string to a {@code X509Certificate} instance.
     *
     * @param pem PEM formatted string
     * @return {@link X509Certificate}
     * @throws CertificateException If conversion fails
     */
    public static X509Certificate convertToX509(String pem) throws CertificateException {
        if (pem == null) {
            return null;
        }

        CertificateFactory certFactory = CertificateFactory.getInstance(X509_CERT_TYPE);
        InputStream inputStream = new ByteArrayInputStream(pem.getBytes());
        return (X509Certificate) certFactory.generateCertificate(inputStream);
    }

    /**
     * Encodes an {@code Certificate} into a PEM-formatted encoding.
     *
     * @param certificate the certificate to encode.
     * @return the PEM-formatted encoding of the certificate.
     * @throws CertificateEncodingException if an encoding error occurs.
     */
    public static String convertToPEM(Certificate certificate) throws CertificateEncodingException {
        if (certificate == null) {
            return null;
        }

        return convertToPEM(certificate.getEncoded());
    }

    /**
     * Converts an encoding into a PEM-formatted string.
     *
     * @param encoding the byte array to encode in the PEM format.
     * @return the PEM-formatted string of the encoding.
     */
    public static String convertToPEM(byte[] encoding) {
        StringBuilder builder = new StringBuilder();
        Base64 encoder = new Base64(LINE_LENGTH, CHUNK_SEPARATOR);
        builder.append(BEGIN_CERT).append("\n");

        String encoded = new String(encoder.encode(encoding), Charset.defaultCharset());
        builder.append(encoded);

        builder.append(END_CERT);
        return builder.toString();
    }

    /**
     * Generates the fingerprint of a certificate. The algorithm is as follows:
     * <ol>
     *  <li>Apply 0xFF mask to remove byte's sign extension
     *  <li>Convert every byte to a hex number
     *  <li>Format every hex number as two characters
     *  <li>Put ':' delimiter between every two characters
     * </ol>
     *
     * @param certificate the certificate to generate a fingerprint of.
     * @return the fingerprint string of the certificate.
     * @throws CertificateEncodingException if an encoding error occurs.
     */
    public static String generateFingerprint(Certificate certificate) throws CertificateEncodingException {
        MessageDigest digest;

        try {
            digest = MessageDigest.getInstance(FINGERPRINT_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("An error occurred while getting the message digest", e);
        }

        // Calculate SHA-1 hash
        byte[] hash = digest.digest(certificate.getEncoded());

        char delimiter = ':';
        int len = hash.length * 2 + hash.length - 1;

        StringBuilder fingerprint = new StringBuilder(len);

        for (int i = 0; i < hash.length; i++) {
            hash[i] &= 0xFF;

            fingerprint.append(String.format("%02x", hash[i]));

            if (i < hash.length - 1) {
                fingerprint.append(delimiter);
            }
        }

        return fingerprint.toString();
    }
}