/*
* Created on 26 juin 2005
*/
package com.opentrust.spi.crypto;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import sun.misc.BASE64Decoder;
/**
* @author mehdi.bouallagui
*/
public class CRLHelper {
/**
* @param x509crl
* @param x509certificate
* @param date
* @return
*/
public static boolean isRevoked(X509CRL x509crl,
X509Certificate x509certificate, Date date) {
if (getRevocationDate(x509crl, x509certificate, date) != null) {
return true;
} else {
return false;
}
}
/**
* get a certificate revocation date
* @param x509crl
* @param x509certificate
* @param date
* @return the rec
*/
public static Date getRevocationDate(X509CRL x509crl,
X509Certificate x509certificate, Date date) {
BigInteger iSerialNumber = x509certificate.getSerialNumber();
X509CRLEntry xEntry = x509crl.getRevokedCertificate(iSerialNumber);
// Le certificat n'appartient pas à la liste de révocation
if (xEntry == null)
return null;
// Le certificat appartient à la CRL. On va vérifier si le
// certificat
// a été révoqué avant ou après la date donnée en paramètre.
Date revocationDate = xEntry.getRevocationDate();
if (revocationDate.before(date)) {
return revocationDate;
} else {
return null;
}
}
public static CRL getCRL(String b64String) throws IOException,
CRLException, CertificateException {
byte[] a = new BASE64Decoder().decodeBuffer(b64String);
ByteArrayInputStream bis = new ByteArrayInputStream(a);
CRL crl = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0)
crl = cf.generateCRL(bis);
return crl;
}
public static CRL getCRL(byte[] bytes) throws IOException, CRLException,
CertificateException {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
return getCRL(bis);
}
public static CRL getCRL(File file) throws IOException,
CertificateException, CRLException {
InputStream fileInputStream = new FileInputStream(file);
CRL crl = getCRL(fileInputStream);
fileInputStream.close();
return crl;
}
private static CRL getCRL(InputStream inputStream) throws CRLException,
IOException, CertificateException {
CRL crl = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (inputStream.available() > 0)
crl = cf.generateCRL(inputStream);
if (crl == null) {
throw new CRLException("Could not parse crl");
}
return crl;
}
public static byte[] getFingerPrint(CRL crl,
String algorithm) throws CRLException,
NoSuchAlgorithmException {
return DigestHelper.getDigest(((X509CRL)crl).getEncoded(), algorithm);
}
private static DERObject getExtensionValue(X509CRL crl, String oid) throws IOException {
if (crl == null) {
return null;
}
byte[] bytes = crl.getExtensionValue(oid);
if (bytes == null) {
return null;
}
ASN1InputStream extValIs = new ASN1InputStream(new ByteArrayInputStream(bytes));
ASN1OctetString octetStr = (ASN1OctetString) extValIs.readObject();
extValIs = new ASN1InputStream(new ByteArrayInputStream(octetStr.getOctets()));
return extValIs.readObject();
}
public static BigInteger getCRLNumber(X509CRL crl) throws CRLException {
BigInteger number = BigInteger.valueOf(0);
try {
DERObject obj = getExtensionValue(crl, X509Extension.cRLNumber.getId());
DERInteger crlnum = CRLNumber.getInstance(obj);
number = crlnum.getPositiveValue();
} catch (IOException e) {
throw new CRLException("Error retrieving CRL number", e);
}
return number;
}
public static byte[] getAuthorityKeyIdentifier(X509CRL crl) throws CRLException {
byte[] result = null;
try {
byte[] extvalue = crl.getExtensionValue(X509Extension.authorityKeyIdentifier.getId());
if (extvalue != null) {
AuthorityKeyIdentifier keyId = new AuthorityKeyIdentifierStructure(extvalue);
result = keyId.getKeyIdentifier();
}
} catch (IOException e) {
throw new CRLException("Error retrieving CRL authority key identifier", e);
}
return result;
}
/**
* Returns true if given certificate is CRL issuer, aka the issuer name and authority key
* identifier match and certificate has CRL signature key usage.
* @param crl
* @param acCertificate
* @return
* @throws CRLException
* @throws CertificateException
*/
public static boolean isCRLIssuer(X509CRL crl, X509Certificate acCertificate) throws CRLException, CertificateException {
boolean result = false;
if (!CertificateHelper.hasKeyUsage(acCertificate, CertificateHelper.KEY_USAGE_CRLSIGN_INDEX))
return false;
X500Principal issuerDN = crl.getIssuerX500Principal();
if (acCertificate.getSubjectX500Principal().equals(issuerDN)) {
byte[] issuerKeyIdASN1 = CRLHelper.getAuthorityKeyIdentifier(crl);
byte[] subjKeyIdANS1 = CertificateHelper.getSubjectKeyIdentifier(acCertificate);
if (subjKeyIdANS1 != null && Arrays.equals(issuerKeyIdASN1, subjKeyIdANS1)) {
result = true;
}
}
return result;
}
}