org.cesecore.certificates.certificate.HashID Maven / Gradle / Ivy
/*************************************************************************
* *
* EJBCA Community: 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.cesecore.certificates.certificate;
import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.util.encoders.Base64;
import org.cesecore.keys.util.KeyTools;
import org.cesecore.util.CertTools;
/**
* An object of this class is identifying one or several certificates or a CRL.
*
* @version $Id: HashID.java 26020 2017-06-14 12:41:08Z mikekushner $
*/
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.
*/
private final boolean isOK;
/*
* The RFC4387 identification string. This is a base64 encoding of the hash.
*/
private final String b64;
/**
* The b64 with \ substituted with %2B to be used for URLs
*/
private final String b64url;
/**
* Key to be used for hash tables.
*/
private 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 = Integer.valueOf(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 cert The issuer DN of the certificate should be the identifier.
* @return the ID
* @throws CertificateException
*/
public static HashID getFromIssuerDN(X509CertificateHolder certificateHolder) throws CertificateException {
return getFromIssuerDN(new JcaX509CertificateConverter().getCertificate(certificateHolder));
}
/**
* @param sDN A string representation of a DN to be as ID. The DN will not be transformed in any way.
* @return the ID.
*/
public static HashID getFromDNString(String sDN) {
// Note that the DN string has to be encoded to an ASN1 with the BC lib. BC endcoding is EJBCA standard.
try {
return getFromDN( new X500Principal(new X500Name(CertTools.isDNReversed(sDN) ? CertTools.reverseDN(sDN) : sDN).getEncoded()));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* @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;
}
public String getB64url() {
return b64url;
}
public Integer getKey() {
return key;
}
public String getB64() {
return b64;
}
}