org.ejbca.core.protocol.certificatestore.HashID.java Source code

Java tutorial

Introduction

Here is the source code for org.ejbca.core.protocol.certificatestore.HashID.java

Source

/*************************************************************************
 *                                                                       *
 *  EJBCA: The OpenSource Certificate Authority                          *
 *                                                                       *
 *  This software is free software; you can redistribute it and/or       *
 *  modify it under the terms of the GNU Lesser General Public           *
 *  License as published by the Free Software Foundation; either         *
 *  version 2.1 of the License, or any later version.                    *
 *                                                                       *
 *  See terms of license at gnu.org.                                     *
 *                                                                       *
 *************************************************************************/
package org.ejbca.core.protocol.certificatestore;

import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.X509Certificate;

import javax.security.auth.x500.X500Principal;

import org.apache.log4j.Logger;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.util.encoders.Base64;
import org.ejbca.util.CertTools;
import org.ejbca.util.keystore.KeyTools;

/**
 * An object of this class is identifying one or several certificates or a CRL.
 * @author Lars Silven PrimeKey
 * @version $Id: HashID.java 15003 2012-06-17 23:55:15Z primelars $
 */
public class HashID {
    /** Log4j instance for Base */
    private static final Logger log = Logger.getLogger(HashID.class);
    /**
     * True if the ID confirms to a RFC4387 ID.
     */
    public final boolean isOK;
    /*
     * The RFC4387 identification string. This is a base64 encoding of the hash.
     */
    public final String b64;
    /**
     * The b64 with \ substituted with %2B to be used for URLs
     */
    public final String b64url;
    /**
     * Key to be used for hash tables.
     */
    public final Integer key;

    private HashID(byte hash[]) {
        final String b64padded = new String(Base64.encode(hash));
        if (b64padded.length() != 28 || b64padded.charAt(27) != '=') {
            this.isOK = false;
            this.b64 = b64padded;
        } else {
            this.isOK = true;
            this.b64 = b64padded.substring(0, 27);
        }
        this.b64url = this.b64.replaceAll("\\+", "%2B");
        this.key = new Integer(new BigInteger(hash).hashCode());
    }

    private static byte[] hashFromPrincipalDN(X500Principal principal) {
        return CertTools.generateSHA1Fingerprint(principal.getEncoded());
    }

    private static HashID getFromDN(X500Principal principal) {
        final HashID id = new HashID(hashFromPrincipalDN(principal));
        if (id.isOK) {
            if (log.isDebugEnabled()) {
                log.debug("The DN '" + principal.getName() + "' is identified by the Hash string '" + id.b64
                        + "' when accessing the VA.");
            }
        } else {
            log.error("The DN '" + principal.getName() + "' has a non valid Hash identification string: " + id.b64);
        }
        return id;
    }

    /**
     * @param cert The subject DN of the certificate should be the identifier.
     * @return the ID
     */
    public static HashID getFromSubjectDN(X509Certificate cert) {
        return getFromDN(cert.getSubjectX500Principal());
    }

    /**
     * @param cert The issuer DN of the certificate should be the identifier.
     * @return the ID
     */
    public static HashID getFromIssuerDN(X509Certificate cert) {
        return getFromDN(cert.getIssuerX500Principal());
    }

    /**
     * @param sDN A string representation of a DN to be as ID.
     * @return the ID.
     */
    public static HashID getFromDN(String sDN) {
        final String ejbcaDN = CertTools.stringToBCDNString(sDN);
        // Note that the DN string has to be encoded to an ASN1 with the BC lib. BC endcoding is EJBCA standard.
        return getFromDN(new X500Principal(new X509Principal(ejbcaDN).getEncoded()));
    }

    /**
     * @param s The hash base64 encoded. See RFC4387
     * @return the ID.
     */
    public static HashID getFromB64(String s) {
        return new HashID(Base64.decode(s.length() == 27 ? s + '=' : s));
    }

    /**
     * @param cert The public key of the certificate will be used as ID.
     * @return the ID.
     */
    public static HashID getFromKeyID(X509Certificate cert) {
        final HashID id = new HashID(KeyTools.createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier());
        if (id.isOK) {
            if (log.isDebugEnabled()) {
                log.debug("The certificate with subject DN '" + cert.getSubjectX500Principal().getName()
                        + "' can be fetched with 'search.cgi?sKIDHash=" + id.b64 + "' from the VA.");
            }
        } else {
            log.error("The certificate with subject DN '" + cert.getSubjectX500Principal().getName()
                    + "' gives a sKIDHash with a not valid format: " + id.b64);
        }
        return id;
    }

    public static HashID getFromAuthorityKeyId(X509Certificate cert) throws IOException {
        final byte hash[] = CertTools.getAuthorityKeyId(cert);
        if (hash == null) {
            return null;
        }
        final HashID id = new HashID(CertTools.getAuthorityKeyId(cert));
        if (!id.isOK) {
            log.error("The certificate with subject DN '" + cert.getSubjectX500Principal().getName()
                    + "' don't have a valid AuthorityKeyId: " + id.b64);
        }
        return id;
    }
}