org.cryptacular.x509.ExtensionReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.saml.opensaml.integration Show documentation
Show all versions of com.liferay.saml.opensaml.integration Show documentation
Liferay SAML OpenSAML Integration
/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.x509;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.AccessDescription;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.PolicyInformation;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.cryptacular.EncodingException;
/**
* Reads X.509v3 extended properties from an {@link java.security.cert.X509Certificate} object. The available properties
* are described in section 4.2 of RFC 2459, http://www.faqs.org/rfcs/rfc2459.html.
*
* @author Middleware Services
*/
public final class ExtensionReader
{
/** The X509Certificate whose extension fields will be read. */
private final X509Certificate certificate;
/**
* Creates a new instance that can read extension fields from the given X.509 certificate.
*
* @param cert Certificate to read.
*/
public ExtensionReader(final X509Certificate cert)
{
certificate = cert;
}
/**
* Reads the value of the extension given by OID or name as defined in section 4.2 of RFC 2459.
*
* @param extensionOidOrName OID or extension name, e.g. 2.5.29.14 orSubjectK eyIdentifier. In the case of extension
* name, the name is case-sensitive and follows the conventions in RFC 2459.
*
* @return Extension type containing data from requested extension field.
*
* @throws EncodingException On certificate field parse errors.
*/
public ASN1Encodable read(final String extensionOidOrName) throws EncodingException
{
if (extensionOidOrName == null) {
throw new IllegalArgumentException("extensionOidOrName cannot be null.");
}
if (extensionOidOrName.contains(".")) {
return read(ExtensionType.fromOid(extensionOidOrName));
} else {
return read(ExtensionType.fromName(extensionOidOrName));
}
}
/**
* Reads the value of the given certificate extension field.
*
* @param extension Extension to read from certificate.
*
* @return Extension type containing data from requested extension field.
*
* @throws EncodingException On certificate field parse errors.
*/
public ASN1Encodable read(final ExtensionType extension)
{
byte[] data = certificate.getExtensionValue(extension.getOid());
if (data == null) {
return null;
}
try {
ASN1Encodable der = ASN1Primitive.fromByteArray(data);
if (der instanceof ASN1OctetString) {
// Strip off octet string "wrapper"
data = ((ASN1OctetString) der).getOctets();
der = ASN1Primitive.fromByteArray(data);
}
return der;
} catch (Exception e) {
throw new EncodingException("ASN.1 parse error", e);
}
}
/**
* Reads the value of the SubjectAlternativeName extension field of the certificate.
*
* @return Collection of subject alternative names or null if the certificate does not define this extension field.
* Note that an empty collection of names is different from a null return value; in the former case the field
* is defined but empty, whereas in the latter the field is not defined on the certificate.
*
* @throws EncodingException On certificate field parse errors.
*/
public GeneralNames readSubjectAlternativeName() throws EncodingException
{
try {
return GeneralNames.getInstance(read(ExtensionType.SubjectAlternativeName));
} catch (RuntimeException e) {
throw new EncodingException("GeneralNames parse error", e);
}
}
/**
* Reads the value of the IssuerAlternativeName
extension field of the certificate.
*
* @return Collection of issuer alternative names or null if the certificate does not define this extension field.
* Note that an empty collection of names is different from a null return value; in the former case the field
* is defined but empty, whereas in the latter the field is not defined on the certificate.
*
* @throws EncodingException On certificate field parse errors.
*/
public GeneralNames readIssuerAlternativeName() throws EncodingException
{
try {
return GeneralNames.getInstance(read(ExtensionType.IssuerAlternativeName));
} catch (RuntimeException e) {
throw new EncodingException("GeneralNames parse error", e);
}
}
/**
* Reads the value of the BasicConstraints
extension field of the certificate.
*
* @return Basic constraints defined on certificate or null if the certificate does not define the field.
*
* @throws EncodingException On certificate field parse errors.
*/
public BasicConstraints readBasicConstraints() throws EncodingException
{
try {
return BasicConstraints.getInstance(read(ExtensionType.BasicConstraints));
} catch (RuntimeException e) {
throw new EncodingException("BasicConstraints parse error", e);
}
}
/**
* Reads the value of the CertificatePolicies
extension field of the certificate.
*
* @return List of certificate policies defined on certificate or null if the certificate does not define the field.
*
* @throws EncodingException On certificate field parse errors.
*/
public List readCertificatePolicies() throws EncodingException
{
final ASN1Encodable data = read(ExtensionType.CertificatePolicies);
if (data == null) {
return null;
}
try {
final ASN1Sequence sequence = ASN1Sequence.getInstance(data);
final List list = new ArrayList<>(sequence.size());
for (int i = 0; i < sequence.size(); i++) {
list.add(PolicyInformation.getInstance(sequence.getObjectAt(i)));
}
return list;
} catch (RuntimeException e) {
throw new EncodingException("PolicyInformation parse error", e);
}
}
/**
* Reads the value of the SubjectKeyIdentifier
extension field of the certificate.
*
* @return Subject key identifier.
*
* @throws EncodingException On certificate field parse errors.
*/
public SubjectKeyIdentifier readSubjectKeyIdentifier() throws EncodingException
{
try {
return SubjectKeyIdentifier.getInstance(read(ExtensionType.SubjectKeyIdentifier));
} catch (RuntimeException e) {
throw new EncodingException("SubjectKeyIdentifier parse error", e);
}
}
/**
* Reads the value of the AuthorityKeyIdentifier
extension field of the certificate.
*
* @return Authority key identifier.
*
* @throws EncodingException On certificate field parse errors.
*/
public AuthorityKeyIdentifier readAuthorityKeyIdentifier() throws EncodingException
{
try {
return AuthorityKeyIdentifier.getInstance(read(ExtensionType.AuthorityKeyIdentifier));
} catch (RuntimeException e) {
throw new EncodingException("AuthorityKeyIdentifier parse error", e);
}
}
/**
* Reads the value of the KeyUsage
extension field of the certificate.
*
* @return Key usage data or null if extension field is not defined.
*
* @throws EncodingException On certificate field parse errors.
*/
public KeyUsage readKeyUsage() throws EncodingException
{
try {
return KeyUsage.getInstance(read(ExtensionType.KeyUsage));
} catch (RuntimeException e) {
throw new EncodingException("KeyUsage parse error", e);
}
}
/**
* Reads the value of the ExtendedKeyUsage
extension field of the certificate.
*
* @return List of supported extended key usages or null if extension is not defined.
*
* @throws EncodingException On certificate field parse errors.
*/
public List readExtendedKeyUsage() throws EncodingException
{
final ASN1Encodable data = read(ExtensionType.ExtendedKeyUsage);
if (data == null) {
return null;
}
try {
final ASN1Sequence sequence = ASN1Sequence.getInstance(data);
final List list = new ArrayList<>(sequence.size());
for (int i = 0; i < sequence.size(); i++) {
list.add(KeyPurposeId.getInstance(sequence.getObjectAt(i)));
}
return list;
} catch (RuntimeException e) {
throw new EncodingException("KeyPurposeId parse error", e);
}
}
/**
* Reads the value of the CRLDistributionPoints
extension field of the certificate.
*
* @return List of CRL distribution points or null if extension is not defined.
*
* @throws EncodingException On certificate field parse errors.
*/
public List readCRLDistributionPoints() throws EncodingException
{
final ASN1Encodable data = read(ExtensionType.CRLDistributionPoints);
if (data == null) {
return null;
}
try {
final ASN1Sequence sequence = ASN1Sequence.getInstance(data);
final List list = new ArrayList<>(sequence.size());
for (int i = 0; i < sequence.size(); i++) {
list.add(DistributionPoint.getInstance(sequence.getObjectAt(i)));
}
return list;
} catch (RuntimeException e) {
throw new EncodingException("DistributionPoint parse error", e);
}
}
/**
* Reads the value of the AuthorityInformationAccess
extension field of the certificate.
*
* @return List of access descriptions or null if extension is not defined.
*
* @throws EncodingException On certificate field parse errors.
*/
public List readAuthorityInformationAccess() throws EncodingException
{
final ASN1Encodable data = read(ExtensionType.AuthorityInformationAccess);
if (data == null) {
return null;
}
try {
final ASN1Sequence sequence = ASN1Sequence.getInstance(data);
final List list = new ArrayList<>(sequence.size());
for (int i = 0; i < sequence.size(); i++) {
list.add(AccessDescription.getInstance(sequence.getObjectAt(i)));
}
return list;
} catch (RuntimeException e) {
throw new EncodingException("AccessDescription parse error", e);
}
}
}