Java tutorial
/* * Copyright (c) 2017 VMware, Inc. All Rights Reserved. * SPDX-License-Identifier: BSD-2-Clause */ package com.vmware.o11n.plugin.crypto.model; import java.io.IOException; import java.io.Serializable; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.util.Date; import java.util.List; import java.util.Map; import javax.naming.InvalidNameException; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.vmware.o11n.plugin.crypto.service.CryptoCertificateService; import com.vmware.o11n.plugin.sdk.annotation.VsoConstructor; import com.vmware.o11n.plugin.sdk.annotation.VsoMethod; import com.vmware.o11n.plugin.sdk.annotation.VsoObject; import com.vmware.o11n.plugin.sdk.annotation.VsoParam; import com.vmware.o11n.plugin.sdk.annotation.VsoProperty; @VsoObject(create = true, strict = true, description = "A scripting object representing a X.509 certificate") public class CryptoCertificate implements Serializable, Cloneable { @Autowired private static CryptoCertificateService service; private final Logger log = LoggerFactory.getLogger(CryptoCertificate.class); /* Constants */ private static final long serialVersionUID = 7252197349636955057L; public static final String TYPE = "CryptoCertificate"; private static final String[] EMPTY_STRING_ARRAY = new String[0]; /* Local write once variables: */ private final X509Certificate cert; private final String certString; //PEM encoded certificate @VsoConstructor(description = "A X.509 Certificate Object") public CryptoCertificate(@VsoParam(description = "PEM encoded certificate") String certString) { if (service == null) { service = new CryptoCertificateService(); } try { this.cert = service.parseCertificate(certString); this.certString = CryptoUtil.pemEncode(this.cert); } catch (CertificateException ce) { throw new IllegalArgumentException("Invalid certificate"); } } public CryptoCertificate(X509Certificate cert) throws CertificateEncodingException { if (service == null) { service = new CryptoCertificateService(); } this.cert = cert; this.certString = CryptoUtil.pemEncode(cert); } /** * * @return */ @VsoProperty(name = "encodedBase64", description = "Encoded form of the certificate encoded as a Base64 string. Hashing this can create a fingerprint") public String getEncodedBase64() { String toReturn = null; try { toReturn = service.getEncodedBase64(this.cert); } catch (CertificateException ce) { log.error(ce.getMessage()); } catch (Throwable e) { log.error("Unexpected exception: " + e.getMessage()); } return toReturn; } /** * * @return */ @VsoProperty(name = "issuedByDN", description = "Distinguished Name the certificate was issued by") public String getIssuedByDN() { return this.cert.getIssuerDN().getName(); } /** * * @return * @throws InvalidNameException */ @VsoProperty(name = "issuedByMap", description = "issuedByDN parsed into key/value pairs") public Map<String, String> getIssuedByMap() throws InvalidNameException { return service.parseDN(this.getIssuedByDN()); } /** * * @return */ @VsoProperty(name = "issuedToDN", description = "Distinguished Name the certificate was issued to") public String getIssuedToDN() { return this.cert.getSubjectDN().getName(); } /** * * @return * @throws InvalidNameException */ @VsoProperty(name = "issuedToMap", description = "issuedToDN parsed into key/value pairs") public Map<String, String> getIssuedToMap() throws InvalidNameException { return service.parseDN(this.getIssuedToDN()); } /** * * @return */ @VsoProperty(name = "pemEncoded", description = "PEM Encoding of the certificate") public String getPemEncoded() { return this.certString; } /** * * @return */ @VsoProperty(name = "publicKeyPem", description = "The RSA Public Key in PEM format found in the certificate") public String getPublicKeyPem() { return service.getPublicKeyPem(this.cert); } /** * * @return */ @VsoProperty(name = "serialNumber", description = "Serial Number of the Certificate") public String getSerialNumber() { return service.getSerialNumber(this.cert); } /** * * @return */ @VsoProperty(name = "sha1Fingerprint", description = "SHA1 fingerprint of the certificate") public String getSha1Fingerprint() { String toReturn = null; try { toReturn = service.getSha1Fingerprint(this.cert); } catch (CertificateException ce) { log.error(ce.getMessage()); } catch (Throwable e) { log.error("Unexpected exception: " + e.getMessage()); } return toReturn; } /** * * @return */ @VsoProperty(name = "sha256Fingerprint", description = "SHA256 fingerprint of the certificate") public String getSha256Fingerprint() { String toReturn = null; try { toReturn = service.getSha256Fingerprint(this.cert); } catch (CertificateException ce) { log.error(ce.getMessage()); } catch (Throwable e) { log.error("Unexpected exception: " + e.getMessage()); } return toReturn; } /** * * @return */ @VsoProperty(name = "signatureAlgorithm", description = "Signature algorithm used by the certificate signer") public String getSignatureAlgorithm() { return this.cert.getSigAlgName(); } /** * * * @return */ @VsoProperty(name = "signatureBase64", description = "Base64 encoded signature of the certificate") public String getSignatureBase64() { byte[] sig = this.cert.getSignature(); return Base64.encodeBase64String(sig); } /** * * @return */ @VsoProperty(name = "subjectAlternativeNames", description = "A list of subject alternative names found in the certificate. Each will have a colon delimited prefix for the type of SAN found. ex: \"dns:\"") public String[] getSubjectAlternativeNames() { try { List<String> san = service.getSubjectAlternativeNames(this.cert); if (san != null && san.size() > 0) { return san.toArray(EMPTY_STRING_ARRAY); } } catch (CertificateParsingException e) { log.error(e.toString()); } return EMPTY_STRING_ARRAY; } /** * * @return */ @VsoMethod(vsoReturnType = "Date", description = "The certificate is valid before this date") public Date getValidBefore() { return this.cert.getNotAfter(); } /** * * @return */ @VsoMethod(vsoReturnType = "Date", description = "The certificate is valid after this date") public Date getValidAfter() { return this.cert.getNotBefore(); } /** * * @param date * @return */ @VsoMethod(vsoReturnType = "boolean", description = "Is the certificate valid based on a provided date") public boolean isValidOn( @VsoParam(vsoType = "Date", description = "Date to check certificate validity on") Date date) { final Date validAfter = this.cert.getNotBefore(); final Date validBefore = this.cert.getNotAfter(); if (validAfter.compareTo(date) > 0) { //'validAfter' is after date //certificate is not valid yet compared to this date return false; } if (validBefore.compareTo(date) < 0) { // 'validBefore is before date' //certificate is expired compared to this date return false; } // passing both these checks, the cert is valid for this date return true; } /** * * @param pemKey * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws IOException */ @VsoMethod(vsoReturnType = "boolean", description = "Verifies the Certificate was signed by a signing certificates private key") public boolean verify(@VsoParam(description = "PEM encoded PublicKey of the signing Certificate") String pemKey) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { return service.verifyCert(this.cert, pemKey); } }