All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.jcajce.provider.asymmetric.x509.X509CRLImpl Maven / Gradle / Ivy

Go to download

The Long Term Stable (LTS) Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains the JCA/JCE provider and low-level API for the BC LTS version 2.73.7 for Java 8 and later.

There is a newer version: 2.73.7
Show newest version
package org.bouncycastle.jcajce.provider.asymmetric.x509;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.security.auth.x500.X500Principal;

import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.CertificateList;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
import org.bouncycastle.asn1.x509.TBSCertList;
import org.bouncycastle.asn1.x509.Time;
import org.bouncycastle.jcajce.CompositePublicKey;
import org.bouncycastle.jcajce.io.OutputStreamFactory;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;

/**
 * The following extensions are listed in RFC 2459 as relevant to CRLs
 * 

* Authority Key Identifier * Issuer Alternative Name * CRL Number * Delta CRL Indicator (critical) * Issuing Distribution Point (critical) */ abstract class X509CRLImpl extends X509CRL { protected JcaJceHelper bcHelper; protected CertificateList c; protected String sigAlgName; protected byte[] sigAlgParams; protected boolean isIndirect; X509CRLImpl(JcaJceHelper bcHelper, CertificateList c, String sigAlgName, byte[] sigAlgParams, boolean isIndirect) { this.bcHelper = bcHelper; this.c = c; this.sigAlgName = sigAlgName; this.sigAlgParams = sigAlgParams; this.isIndirect = isIndirect; } /** * Will return true if any extensions are present and marked * as critical as we currently dont handle any extensions! */ public boolean hasUnsupportedCriticalExtension() { Set extns = getCriticalExtensionOIDs(); if (extns == null) { return false; } extns.remove(Extension.issuingDistributionPoint.getId()); extns.remove(Extension.deltaCRLIndicator.getId()); return !extns.isEmpty(); } private Set getExtensionOIDs(boolean critical) { if (this.getVersion() == 2) { Extensions extensions = c.getTBSCertList().getExtensions(); if (extensions != null) { Set set = new HashSet(); Enumeration e = extensions.oids(); while (e.hasMoreElements()) { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); Extension ext = extensions.getExtension(oid); if (critical == ext.isCritical()) { set.add(oid.getId()); } } return set; } } return null; } public Set getCriticalExtensionOIDs() { return getExtensionOIDs(true); } public Set getNonCriticalExtensionOIDs() { return getExtensionOIDs(false); } public byte[] getExtensionValue(String oid) { ASN1OctetString extValue = getExtensionValue(c, oid); if (null != extValue) { try { return extValue.getEncoded(); } catch (Exception e) { throw new IllegalStateException("error parsing " + e.toString()); } } return null; } public void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { doVerify(key, new SignatureCreator() { public Signature createSignature(String sigName) throws NoSuchAlgorithmException, NoSuchProviderException { try { return bcHelper.createSignature(sigName); } catch (Exception e) { return Signature.getInstance(sigName); } } }); } public void verify(PublicKey key, final String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { doVerify(key, new SignatureCreator() { public Signature createSignature(String sigName) throws NoSuchAlgorithmException, NoSuchProviderException { if (sigProvider != null) { return Signature.getInstance(sigName, sigProvider); } else { return Signature.getInstance(sigName); } } }); } public void verify(PublicKey key, final Provider sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { try { doVerify(key, new SignatureCreator() { public Signature createSignature(String sigName) throws NoSuchAlgorithmException, NoSuchProviderException { if (sigProvider != null) { return Signature.getInstance(getSigAlgName(), sigProvider); } else { return Signature.getInstance(getSigAlgName()); } } }); } catch (NoSuchProviderException e) { // can't happen, but just in case throw new NoSuchAlgorithmException("provider issue: " + e.getMessage()); } } private void doVerify(PublicKey key, SignatureCreator sigCreator) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, NoSuchProviderException { if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature())) { throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList."); } if (key instanceof CompositePublicKey && X509SignatureUtil.isCompositeAlgorithm(c.getSignatureAlgorithm())) { List pubKeys = ((CompositePublicKey)key).getPublicKeys(); ASN1Sequence keySeq = ASN1Sequence.getInstance(c.getSignatureAlgorithm().getParameters()); ASN1Sequence sigSeq = ASN1Sequence.getInstance(ASN1BitString.getInstance(c.getSignature()).getBytes()); boolean success = false; for (int i = 0; i != pubKeys.size(); i++) { if (pubKeys.get(i) == null) { continue; } AlgorithmIdentifier sigAlg = AlgorithmIdentifier.getInstance(keySeq.getObjectAt(i)); String sigName = X509SignatureUtil.getSignatureName(sigAlg); Signature signature = sigCreator.createSignature(sigName); SignatureException sigExc = null; try { checkSignature( (PublicKey)pubKeys.get(i), signature, sigAlg.getParameters(), ASN1BitString.getInstance(sigSeq.getObjectAt(i)).getBytes()); success = true; } catch (SignatureException e) { sigExc = e; } if (sigExc != null) { throw sigExc; } } if (!success) { throw new InvalidKeyException("no matching key found"); } } else if (X509SignatureUtil.isCompositeAlgorithm(c.getSignatureAlgorithm())) { ASN1Sequence keySeq = ASN1Sequence.getInstance(c.getSignatureAlgorithm().getParameters()); ASN1Sequence sigSeq = ASN1Sequence.getInstance(ASN1BitString.getInstance(c.getSignature()).getBytes()); boolean success = false; for (int i = 0; i != sigSeq.size(); i++) { AlgorithmIdentifier sigAlg = AlgorithmIdentifier.getInstance(keySeq.getObjectAt(i)); String sigName = X509SignatureUtil.getSignatureName(sigAlg); SignatureException sigExc = null; try { Signature signature = sigCreator.createSignature(sigName); checkSignature( key, signature, sigAlg.getParameters(), ASN1BitString.getInstance(sigSeq.getObjectAt(i)).getBytes()); success = true; } catch (InvalidKeyException e) { // ignore } catch (NoSuchAlgorithmException e) { // ignore } catch (SignatureException e) { sigExc = e; } if (sigExc != null) { throw sigExc; } } if (!success) { throw new InvalidKeyException("no matching key found"); } } else { Signature sig = sigCreator.createSignature(getSigAlgName()); if (sigAlgParams == null) { checkSignature(key, sig, null, this.getSignature()); } else { try { checkSignature(key, sig, ASN1Primitive.fromByteArray(sigAlgParams), this.getSignature()); } catch (IOException e) { throw new SignatureException("cannot decode signature parameters: " + e.getMessage()); } } } } private void checkSignature(PublicKey key, Signature sig, ASN1Encodable sigAlgParams, byte[] encSig) throws NoSuchAlgorithmException, SignatureException, InvalidKeyException, CRLException { if (sigAlgParams != null) { // needs to be called before initVerify(). X509SignatureUtil.setSignatureParameters(sig, sigAlgParams); } sig.initVerify(key); try { OutputStream sigOut = new BufferedOutputStream(OutputStreamFactory.createStream(sig), 512); c.getTBSCertList().encodeTo(sigOut, ASN1Encoding.DER); sigOut.close(); } catch (IOException e) { throw new CRLException(e.toString()); } if (!sig.verify(encSig)) { throw new SignatureException("CRL does not verify with supplied public key."); } } public int getVersion() { return c.getVersionNumber(); } public Principal getIssuerDN() { return getIssuerX500Principal(); } public X500Principal getIssuerX500Principal() { try { return new X500Principal(c.getIssuer().getEncoded()); } catch (IOException e) { throw new IllegalStateException("can't encode issuer DN"); } } public Date getThisUpdate() { return c.getThisUpdate().getDate(); } public Date getNextUpdate() { Time nextUpdate = c.getNextUpdate(); return null == nextUpdate ? null : nextUpdate.getDate(); } private Set loadCRLEntries() { Set entrySet = new HashSet(); Enumeration certs = c.getRevokedCertificateEnumeration(); X500Name previousCertificateIssuer = null; // the issuer while (certs.hasMoreElements()) { TBSCertList.CRLEntry entry = (TBSCertList.CRLEntry)certs.nextElement(); X509CRLEntryObject crlEntry = new X509CRLEntryObject(entry, isIndirect, previousCertificateIssuer); entrySet.add(crlEntry); if (isIndirect && entry.hasExtensions()) { Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer); if (currentCaName != null) { previousCertificateIssuer = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName()); } } } return entrySet; } public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) { Enumeration certs = c.getRevokedCertificateEnumeration(); X500Name previousCertificateIssuer = null; // the issuer while (certs.hasMoreElements()) { TBSCertList.CRLEntry entry = (TBSCertList.CRLEntry)certs.nextElement(); if (entry.getUserCertificate().hasValue(serialNumber)) { return new X509CRLEntryObject(entry, isIndirect, previousCertificateIssuer); } if (isIndirect && entry.hasExtensions()) { Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer); if (currentCaName != null) { previousCertificateIssuer = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName()); } } } return null; } public Set getRevokedCertificates() { Set entrySet = loadCRLEntries(); if (!entrySet.isEmpty()) { return Collections.unmodifiableSet(entrySet); } return null; } public byte[] getTBSCertList() throws CRLException { try { return c.getTBSCertList().getEncoded(ASN1Encoding.DER); } catch (IOException e) { throw new CRLException(e.toString()); } } public byte[] getSignature() { return c.getSignature().getOctets(); } public String getSigAlgName() { return sigAlgName; } public String getSigAlgOID() { return c.getSignatureAlgorithm().getAlgorithm().getId(); } public byte[] getSigAlgParams() { return Arrays.clone(sigAlgParams); } /** * Returns a string representation of this CRL. * * @return a string representation of this CRL. */ public String toString() { StringBuffer buf = new StringBuffer(); String nl = Strings.lineSeparator(); buf.append(" Version: ").append(this.getVersion()).append( nl); buf.append(" IssuerDN: ").append(this.getIssuerDN()) .append(nl); buf.append(" This update: ").append(this.getThisUpdate()) .append(nl); buf.append(" Next update: ").append(this.getNextUpdate()) .append(nl); buf.append(" Signature Algorithm: ").append(this.getSigAlgName()) .append(nl); X509SignatureUtil.prettyPrintSignature(this.getSignature(), buf, nl); Extensions extensions = c.getTBSCertList().getExtensions(); if (extensions != null) { Enumeration e = extensions.oids(); if (e.hasMoreElements()) { buf.append(" Extensions: ").append(nl); } while (e.hasMoreElements()) { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); Extension ext = extensions.getExtension(oid); if (ext.getExtnValue() != null) { byte[] octs = ext.getExtnValue().getOctets(); ASN1InputStream dIn = new ASN1InputStream(octs); buf.append(" critical(").append( ext.isCritical()).append(") "); try { if (oid.equals(Extension.cRLNumber)) { buf.append( new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } else if (oid.equals(Extension.deltaCRLIndicator)) { buf.append( "Base CRL: " + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } else if (oid .equals(Extension.issuingDistributionPoint)) { buf.append( IssuingDistributionPoint.getInstance(dIn.readObject())).append(nl); } else if (oid .equals(Extension.cRLDistributionPoints)) { buf.append( CRLDistPoint.getInstance(dIn.readObject())).append(nl); } else if (oid.equals(Extension.freshestCRL)) { buf.append( CRLDistPoint.getInstance(dIn.readObject())).append(nl); } else { buf.append(oid.getId()); buf.append(" value = ").append( ASN1Dump.dumpAsString(dIn.readObject())) .append(nl); } } catch (Exception ex) { buf.append(oid.getId()); buf.append(" value = ").append("*****").append(nl); } } else { buf.append(nl); } } } Set set = getRevokedCertificates(); if (set != null) { Iterator it = set.iterator(); while (it.hasNext()) { buf.append(it.next()); buf.append(nl); } } return buf.toString(); } /** * Checks whether the given certificate is on this CRL. * * @param cert the certificate to check for. * @return true if the given certificate is on this CRL, * false otherwise. */ public boolean isRevoked(Certificate cert) { if (!cert.getType().equals("X.509")) { throw new IllegalArgumentException("X.509 CRL used with non X.509 Cert"); } Enumeration certs = c.getRevokedCertificateEnumeration(); X500Name caName = c.getIssuer(); if (certs.hasMoreElements()) { BigInteger serial = ((X509Certificate)cert).getSerialNumber(); while (certs.hasMoreElements()) { TBSCertList.CRLEntry entry = TBSCertList.CRLEntry.getInstance(certs.nextElement()); if (isIndirect && entry.hasExtensions()) { Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer); if (currentCaName != null) { caName = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName()); } } if (entry.getUserCertificate().hasValue(serial)) { X500Name issuer; if (cert instanceof X509Certificate) { issuer = X500Name.getInstance(((X509Certificate)cert).getIssuerX500Principal().getEncoded()); } else { try { issuer = org.bouncycastle.asn1.x509.Certificate.getInstance(cert.getEncoded()).getIssuer(); } catch (CertificateEncodingException e) { throw new IllegalArgumentException("Cannot process certificate: " + e.getMessage()); } } if (!caName.equals(issuer)) { return false; } return true; } } } return false; } protected static byte[] getExtensionOctets(CertificateList c, String oid) { ASN1OctetString extValue = getExtensionValue(c, oid); if (null != extValue) { return extValue.getOctets(); } return null; } protected static ASN1OctetString getExtensionValue(CertificateList c, String oid) { Extensions exts = c.getTBSCertList().getExtensions(); if (null != exts) { Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); if (null != ext) { return ext.getExtnValue(); } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy