package model; import helpers.CertificateHelper; import java.io.IOException; import java.math.BigInteger; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; public class BurpCertificate { private X509Certificate certificate; private PrivateKey privateKey; private PublicKey publicKey; private String source; public BurpCertificate() { } public BurpCertificate(X509Certificate certificate) { this.certificate = certificate; source = "default"; } public BurpCertificate(PublicKey publicKey, PrivateKey privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public void setPrivateKey(PrivateKey privateKey) { this.privateKey = privateKey; } public void setPublicKey(PublicKey publicKey) { this.publicKey = publicKey; } public void setCertificate(X509Certificate certificate) { this.certificate = certificate; } public X509Certificate getCertificate() { return certificate; } public int getVersionNumber() { return certificate.getVersion(); } public BigInteger getSerialNumberBigInteger() { return certificate.getSerialNumber(); } public String getSerialNumber() { return CertificateHelper.bigIntegerToHexString(getSerialNumberBigInteger()); } public String getIssuer() { return certificate.getIssuerX500Principal().toString(); } public Date getNotBefore() { return certificate.getNotBefore(); } public Date getNotAfter() { return certificate.getNotAfter(); } public boolean isValidOn(Date date) { try { certificate.checkValidity(date); return true; } catch (CertificateExpiredException | CertificateNotYetValidException e) { return false; } } public String getSubject() { return certificate.getSubjectX500Principal().toString(); } public boolean hasExtensions() { return (!certificate.getCriticalExtensionOIDs().isEmpty()) || (!certificate.getNonCriticalExtensionOIDs().isEmpty()); } public int getExtensionsCount() { return certificate.getCriticalExtensionOIDs().size() + certificate.getNonCriticalExtensionOIDs().size(); } public String getSignatureAlgorithm() { return certificate.getSigAlgName(); } public String getSignature() { return CertificateHelper.addHexColons(CertificateHelper.byteArrayToHex(certificate.getSignature())); } public String getPublicKeyAlgorithm() { return certificate.getPublicKey().getAlgorithm(); } public PrivateKey getPrivateKey() { return privateKey; } public PublicKey getPublicKey() { return publicKey; } public int getKeySize() { if (certificate.getPublicKey() instanceof RSAPublicKey) { RSAPublicKey pub = (RSAPublicKey) certificate.getPublicKey(); return pub.getModulus().bitLength(); } else { return 0; } } public String getPublicKeyModulus() { // https://stackoverflow.com/questions/20897065/how-to-get-exponent-and-modulus-value-of-rsa-public-key-from-pfx-file-pem-file-i if (certificate.getPublicKey() instanceof RSAPublicKey) { RSAPublicKey pub = (RSAPublicKey) certificate.getPublicKey(); return CertificateHelper.addHexColons(pub.getModulus().toString(16)); } else { return ""; } } public String getPublicKeyExponent() { Pattern pattern = Pattern.compile("exponent: ([0-9]*)"); Matcher matcher = pattern.matcher(certificate.getPublicKey().toString()); if (matcher.find()) { return matcher.group(1); } return "Not found"; } /* * Extensions */ public List<String> getKeyUsage() { boolean[] keyUsage = certificate.getKeyUsage(); List<String> keyUsageList = new LinkedList<>(); if (keyUsage == null) { return keyUsageList; } for (int i = 0; i < keyUsage.length; i++) { if (keyUsage[i]) { keyUsageList.add(ObjectIdentifier.getKeyUsage(i)); } } return keyUsageList; } public List<String> getSubjectAlternativeNames() { List<String> subjectAlternativeNames = new LinkedList<String>(); try { if (certificate.getSubjectAlternativeNames() == null) { return subjectAlternativeNames; } for (List<?> i : certificate.getSubjectAlternativeNames()) { subjectAlternativeNames.add(i.get(1) + " (" + ObjectIdentifier.getSubjectAlternativeNames((Integer) i.get(0)) + ")"); } } catch (CertificateParsingException e) { e.printStackTrace(); } return subjectAlternativeNames; } public List<String> getIssuerAlternativeNames() { List<String> issuerAlternativeNames = new LinkedList<String>(); try { if (certificate.getIssuerAlternativeNames() == null) { return issuerAlternativeNames; } for (List<?> i : certificate.getIssuerAlternativeNames()) { issuerAlternativeNames.add(i.get(1) + " (" + ObjectIdentifier.getSubjectAlternativeNames((Integer) i.get(0)) + ")"); } } catch (CertificateParsingException e) { e.printStackTrace(); } return issuerAlternativeNames; } public boolean isCa() { return certificate.getBasicConstraints() == -1 ? false : true; } public String getPathLimit() { int pathLimit = certificate.getBasicConstraints(); if (pathLimit != -1) { return pathLimit == Integer.MAX_VALUE ? "No Limit" : String.valueOf(pathLimit); } else { return ""; } } public boolean hasNoPathLimit(){ return certificate.getBasicConstraints() == Integer.MAX_VALUE; } public String getBasicConstraints() { String basicConstraints = ""; switch (certificate.getBasicConstraints()) { case -1: basicConstraints = "CA: False"; break; case Integer.MAX_VALUE: basicConstraints = "CA: True. No path limit."; break; default: basicConstraints = "CA: True. Path limit: " + certificate.getBasicConstraints() + "."; } return basicConstraints; } public List<String> getExtendedKeyUsage() { List<String> extendedKeyUsage = new LinkedList<>(); try { if (certificate.getExtendedKeyUsage() == null) { return extendedKeyUsage; } for (String i : certificate.getExtendedKeyUsage()) { extendedKeyUsage.add(ObjectIdentifier.getExtendedKeyUsage(i)); } } catch (CertificateParsingException e) { e.printStackTrace(); } return extendedKeyUsage; } public String getAuthorityKeyIdentifier() { byte[] e = certificate.getExtensionValue(Extension.authorityKeyIdentifier.getId()); if (e == null) { return ""; } ASN1Primitive ap; byte[] k = {}; try { ap = JcaX509ExtensionUtils.parseExtensionValue(e); k = ASN1Sequence.getInstance(ap.getEncoded()).getEncoded(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // Very ugly hack to extract the SHA1 Hash (59 Hex Chars) from the // Extension :( return CertificateHelper.addHexColons(CertificateHelper.byteArrayToHex(k)).substring(12, k.length * 3 - 1); } public String getSubjectKeyIdentifier() { // https://stackoverflow.com/questions/6523081/why-doesnt-my-key-identifier-match byte[] e = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); if (e == null) { return ""; } ASN1Primitive ap; byte[] k = {}; try { ap = JcaX509ExtensionUtils.parseExtensionValue(e); k = ASN1OctetString.getInstance(ap.getEncoded()).getOctets(); } catch (IOException e1) { e1.printStackTrace(); } return CertificateHelper.addHexColons(CertificateHelper.byteArrayToHex(k)); } public List<BurpCertificateExtension> getAllExtensions() { List<BurpCertificateExtension> allExtensions = new LinkedList<>(); Set<String> criticalExtensionOIDs = certificate.getCriticalExtensionOIDs(); if (criticalExtensionOIDs != null) { for (String i : criticalExtensionOIDs) { allExtensions.add(new BurpCertificateExtension(i, true, certificate.getExtensionValue(i))); } } Set<String> nonCriticalExtensionOIDs = certificate.getNonCriticalExtensionOIDs(); if (nonCriticalExtensionOIDs != null) { for (String i : nonCriticalExtensionOIDs) { allExtensions.add(new BurpCertificateExtension(i, false, certificate.getExtensionValue(i))); } } return allExtensions; } public boolean hasPrivateKey() { return getPrivateKey() != null ? true : false; } public String toString() { String toString = getSubject(); toString += " ["; toString += "Private Key: " + hasPrivateKey(); toString += "; Source: " + getSource(); toString += "]"; return toString; } }