Java tutorial
//$Header: /cvsroot/mec-as2/b47/de/mendelson/util/security/cert/KeystoreCertificate.java,v 1.1 2015/01/06 11:07:57 heller Exp $ package de.mendelson.util.security.cert; import java.io.Serializable; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.cert.CertPath; import java.security.cert.CertPathBuilder; import java.security.cert.CertPathBuilderException; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorResult; import java.security.cert.CertStore; import java.security.cert.CertStoreParameters; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXCertPathBuilderResult; import java.security.cert.PKIXCertPathValidatorResult; import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1String; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x509.CRLDistPoint; import org.bouncycastle.asn1.x509.DistributionPoint; import org.bouncycastle.asn1.x509.DistributionPointName; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyUsage; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. Other product * and brand names are trademarks of their respective owners. */ /** * Object that stores a single configuration certificate/key * * @author S.Heller * @version $Revision: 1.1 $ */ public class KeystoreCertificate implements Comparable, Serializable { private String alias = ""; private X509Certificate certificate = null; private boolean isKeyPair = false; public KeystoreCertificate() { } /** * Returns the extension value "extended key usage", OID 2.5.29.37 * */ public List<String> getExtendedKeyUsage() { HashMap<String, String> oidMap = new HashMap<String, String>(); oidMap.put("1.3.6.1.5.5.7.3.2", "Client authentication"); oidMap.put("1.3.6.1.5.5.7.3.1", "Webserver authentication"); oidMap.put("1.3.6.1.5.5.7.3.5", "IPSec end system"); oidMap.put("1.3.6.1.5.5.7.3.6", "IPSec tunnel"); oidMap.put("1.3.6.1.5.5.7.3.3", "Code signing"); oidMap.put("1.3.6.1.5.5.7.3.7", "IPSec user"); oidMap.put("1.3.6.1.5.5.7.3.4", "Email protection"); oidMap.put("1.3.6.1.5.5.7.3.8", "Timestamping"); oidMap.put("2.16.840.1.113733.1.8.1", "Verisign Server Gated Crypto"); //Netscape extended key usages oidMap.put("2.16.840.1.113730.4.1", "Netscape Server Gated Crypto"); oidMap.put("2.16.840.1.113730.1.2", "Netscape base URL"); oidMap.put("2.16.840.1.113730.1.8", "Netscape CA policy URL"); oidMap.put("2.16.840.1.113730.1.4", "Netscape CA revocation URL"); oidMap.put("2.16.840.1.113730.1.7", "Netscape cert renewal URL"); oidMap.put("2.16.840.1.113730.2.5", "Netscape cert sequence"); oidMap.put("2.16.840.1.113730.1.1", "Netscape cert type"); oidMap.put("2.16.840.1.113730.1.13", "Netscape comment"); oidMap.put("2.16.840.1.113730.1.3", "Netscape revocation URL"); oidMap.put("2.16.840.1.113730.1.12", "Netscape SSL server name"); //MS extended key usages oidMap.put("1.3.6.1.4.1.311.10.3.3", "Microsoft Server Gated Crypto"); oidMap.put("1.3.6.1.4.1.311.20.2.2", "Smart card logon"); oidMap.put("1.3.6.1.4.1.311.10.3.4", "Encrypting filesystem"); oidMap.put("1.3.6.1.4.1.311.10.3.12", "Document signing"); oidMap.put("1.3.6.1.4.1.311.21.5", "CA encryption certificate"); oidMap.put("1.3.6.1.4.1.311.10.3.1", "Microsoft trust list signing"); oidMap.put("1.3.6.1.4.1.311.10.3.4.1", "File recovery"); oidMap.put("1.3.6.1.4.1.311.10.3.11", "Key recovery"); oidMap.put("1.3.6.1.4.1.311.10.3.10", "Qualified subordination"); oidMap.put("1.3.6.1.4.1.311.10.3.9", "Root list signer"); List<String> extendedKeyUsage = new ArrayList<String>(); byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.37"); if (extensionValue == null) { return (extendedKeyUsage); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); ASN1Sequence asn1Sequence = (ASN1Sequence) ASN1Primitive.fromByteArray(octedBytes); for (int i = 0; i < asn1Sequence.size(); i++) { String oid = (asn1Sequence.getObjectAt(i).toASN1Primitive().toString()); if (oidMap.containsKey(oid)) { extendedKeyUsage.add(oidMap.get(oid)); } else { extendedKeyUsage.add(oid); } } } catch (Exception e) { e.printStackTrace(); } return (extendedKeyUsage); } public List<String> getAuthorityKeyIdentifier() { List<String> authorityKeyIdentifierList = new ArrayList<String>(); byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.35"); if (extensionValue == null) { return (authorityKeyIdentifierList); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); ASN1Sequence asn1Sequence = (ASN1Sequence) ASN1Primitive.fromByteArray(octedBytes); for (int i = 0, len = asn1Sequence.size(); i < len; i++) { DERTaggedObject derTagObj = (DERTaggedObject) asn1Sequence.getObjectAt(i); if (derTagObj.getTagNo() == 0) { DEROctetString octetStr = (DEROctetString) derTagObj.getObject(); byte[] identifier = octetStr.getOctets(); authorityKeyIdentifierList.add("[Key identifier] " + byteArrayToHexStr(identifier)); } else if (derTagObj.getTagNo() == 2) { DEROctetString octetStr = (DEROctetString) derTagObj.getObject(); byte[] identifier = octetStr.getOctets(); authorityKeyIdentifierList.add("[Serial] " + byteArrayToHexStr(identifier)); } } } catch (Exception e) { e.printStackTrace(); } return (authorityKeyIdentifierList); } public List<String> getSubjectKeyIdentifier() { List<String> subjectKeyIdentifierList = new ArrayList<String>(); byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.14"); if (extensionValue == null) { return (subjectKeyIdentifierList); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); DEROctetString octetStr = (DEROctetString) ASN1Primitive.fromByteArray(octedBytes); byte[] identifier = octetStr.getOctets(); subjectKeyIdentifierList.add(byteArrayToHexStr(identifier)); } catch (Exception e) { e.printStackTrace(); } return (subjectKeyIdentifierList); } /** * Returns the key usages of this cert, OID 2.5.29.15 */ public List<String> getKeyUsages() { List<String> keyUsages = new ArrayList<String>(); byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.15"); if (extensionValue == null) { return (keyUsages); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); //bit encoded values for the key usage int val = KeyUsage.getInstance(ASN1Primitive.fromByteArray(octedBytes)).getPadBits(); //bit 0 if ((val & KeyUsage.digitalSignature) == KeyUsage.digitalSignature) { keyUsages.add("Digital signature"); } //bit 1 if ((val & KeyUsage.nonRepudiation) == KeyUsage.nonRepudiation) { keyUsages.add("Non repudiation"); } //bit 2 if ((val & KeyUsage.keyEncipherment) == KeyUsage.keyEncipherment) { keyUsages.add("Key encipherment"); } //bit 3 if ((val & KeyUsage.dataEncipherment) == KeyUsage.dataEncipherment) { keyUsages.add("Data encipherment"); } //bit 4 if ((val & KeyUsage.keyAgreement) == KeyUsage.keyAgreement) { keyUsages.add("Key agreement"); } //bit 5 if ((val & KeyUsage.keyCertSign) == KeyUsage.keyCertSign) { keyUsages.add("Key certificate signing"); } //bit6 if ((val & KeyUsage.cRLSign) == KeyUsage.cRLSign) { keyUsages.add("CRL signing"); } if ((val & KeyUsage.decipherOnly) == KeyUsage.decipherOnly) { keyUsages.add("Decipher"); } if ((val & KeyUsage.encipherOnly) == KeyUsage.encipherOnly) { keyUsages.add("Encipher"); } } catch (Exception e) { e.printStackTrace(); } return (keyUsages); } public BigInteger getModulus() { PublicKey key = this.certificate.getPublicKey(); if (key instanceof RSAPublicKey) { RSAPublicKey rsaKey = (RSAPublicKey) key; return (rsaKey.getModulus()); } return (BigInteger.ZERO); } public BigInteger getPublicExponent() { PublicKey key = this.certificate.getPublicKey(); if (key instanceof RSAPublicKey) { RSAPublicKey rsaKey = (RSAPublicKey) key; return (rsaKey.getPublicExponent()); } return (BigInteger.ZERO); } /** * Returns the subject alternative name of this cert, OID 2.5.29.17 */ public List<String> getSubjectAlternativeNames() { List<String> alternativeNames = new ArrayList<String>(); byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.17"); if (extensionValue == null) { return (alternativeNames); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); GeneralName[] names = (GeneralNames.getInstance(ASN1Primitive.fromByteArray(octedBytes))).getNames(); for (GeneralName name : names) { alternativeNames.add(((ASN1String) name.getName()).getString() + " (" + this.generalNameTagNoToString(name) + ")"); } } catch (Exception e) { e.printStackTrace(); } return (alternativeNames); } /** * Converts the tag no of a general name to a human readable value */ private String generalNameTagNoToString(GeneralName name) { if (name.getTagNo() == GeneralName.dNSName) { return ("DNS name"); } if (name.getTagNo() == GeneralName.directoryName) { return ("Directory name"); } if (name.getTagNo() == GeneralName.ediPartyName) { return ("EDI party name"); } if (name.getTagNo() == GeneralName.iPAddress) { return ("IP address"); } if (name.getTagNo() == GeneralName.otherName) { return ("Other name"); } if (name.getTagNo() == GeneralName.registeredID) { return ("Registered ID"); } if (name.getTagNo() == GeneralName.rfc822Name) { return ("RFC822 name"); } if (name.getTagNo() == GeneralName.uniformResourceIdentifier) { return ("URI"); } if (name.getTagNo() == GeneralName.x400Address) { return ("x.400 address"); } return (""); } /** * Get extension values for CRL Distribution Points as a string list or an * empty list if an exception occured or the extension doesnt exist OID * 2.5.29.31 */ public List<String> getCrlDistributionURLs() { List<String> ulrList = new ArrayList<String>(); //CRL destribution points has OID 2.5.29.31 byte[] extensionValue = this.certificate.getExtensionValue("2.5.29.31"); if (extensionValue == null) { return (ulrList); } try { byte[] octedBytes = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionValue)).getOctets(); CRLDistPoint distPoint = CRLDistPoint.getInstance(ASN1Primitive.fromByteArray(octedBytes)); DistributionPoint[] points = distPoint.getDistributionPoints(); for (DistributionPoint point : points) { DistributionPointName distributionPointName = point.getDistributionPoint(); if (distributionPointName != null) { if (distributionPointName.getType() == DistributionPointName.FULL_NAME) { GeneralNames generalNames = (GeneralNames) distributionPointName.getName(); for (GeneralName generalName : generalNames.getNames()) { //generalName.getTagNo() is GeneralName.uniformResourceIdentifier in this case ulrList.add(((ASN1String) generalName.getName()).getString()); } } } } } catch (Exception e) { //nop } return (ulrList); } /** * Returns the enwrapped certificate version */ public int getVersion() { return (this.certificate.getVersion()); } public String getSigAlgName() { return (this.certificate.getSigAlgName()); } public String getPublicKeyAlgorithm() { return (this.certificate.getPublicKey().getAlgorithm()); } /** * Valid date start */ public Date getNotBefore() { return (this.certificate.getNotBefore()); } /** * Valid date end */ public Date getNotAfter() { return (this.certificate.getNotAfter()); } public String getSubjectDN() { return (this.certificate.getSubjectDN().toString()); } public String getIssuerDN() { return (this.certificate.getIssuerDN().toString()); } /** * Returns the serial number as decimal */ public String getSerialNumberDEC() { return (this.certificate.getSerialNumber().toString()); } /** * Returns the serial number as decimal */ public String getSerialNumberHEX() { return (this.certificate.getSerialNumber().toString(16).toUpperCase()); } public void setAlias(String alias) { if (alias == null) { alias = ""; } this.alias = alias; } public void setCertificate(X509Certificate certificate) { this.certificate = certificate; } public void setIsKeyPair(boolean isKeyPair) { this.isKeyPair = isKeyPair; } public X509Certificate getX509Certificate() { return (this.certificate); } public boolean getIsKeyPair() { return (this.isKeyPair); } public boolean isRootCertificate() { return (this.isSelfSigned() && this.certificate.getBasicConstraints() != -1); } public boolean isSelfSigned() { X500Principal subject = this.certificate.getSubjectX500Principal(); X500Principal issuer = this.certificate.getIssuerX500Principal(); return (subject.equals(issuer)); } public String getAlias() { return (this.alias); } public int getPublicKeyLength() { PublicKey key = this.certificate.getPublicKey(); if (key instanceof RSAPublicKey) { RSAPublicKey rsaKey = (RSAPublicKey) key; return (rsaKey.getModulus().bitLength()); } return (0); } public byte[] getFingerPrintBytesSHA1() { return (this.getFingerPrintBytes("SHA1")); } public byte[] getFingerPrintBytesMD5() { return (this.getFingerPrintBytes("MD5")); } public String getFingerPrintSHA1() { return (this.getFingerPrint("SHA1")); } public String getFingerPrintMD5() { return (this.getFingerPrint("MD5")); } /** * Deserializes a fingerprint string to a byte array It is assumed that the * fingerprint string has the format hex:hex:hex */ public static byte[] fingerprintStrToBytes(String fingerprintStr) { String[] token = fingerprintStr.split(":"); byte[] bytes = new byte[token.length]; for (int i = 0; i < token.length; i++) { while (token[i].length() < 2) { token[i] = "0" + token[i]; } bytes[i] = fromHexString(token[i])[0]; } return (bytes); } private static byte[] fromHexString(final String encoded) { if ((encoded.length() % 2) != 0) { throw new IllegalArgumentException("Input string must contain an even number of characters"); } final byte result[] = new byte[encoded.length() / 2]; final char enc[] = encoded.toCharArray(); for (int i = 0; i < enc.length; i += 2) { StringBuilder curr = new StringBuilder(2); curr.append(enc[i]).append(enc[i + 1]); result[i / 2] = (byte) Integer.parseInt(curr.toString(), 16); } return result; } private static String byteArrayToHexStr(byte[] byteArray) { StringBuilder hextStringBuffer = new StringBuilder(); for (int i = 0; i < byteArray.length; i++) { if (i > 0) { hextStringBuffer.append(":"); } String singleByte = Integer.toHexString(byteArray[i] & 0xFF).toUpperCase(); if (singleByte.length() == 0) { hextStringBuffer.append("00"); } else if (singleByte.length() == 1) { hextStringBuffer.append("0"); } hextStringBuffer.append(singleByte); } return hextStringBuffer.toString(); } /** * Serializes a fingerprint string from a byte array to a String It is * assumed that the fingerprint string has the format hex:hex:hex */ public static String fingerprintBytesToStr(byte[] fingerprintBytes) { return (byteArrayToHexStr(fingerprintBytes)); } /** * @param digest to create the hash value, please use SHA1 or MD5 only * */ private byte[] getFingerPrintBytes(String digest) { try { MessageDigest messageDigest = MessageDigest.getInstance(digest); return (messageDigest.digest(this.certificate.getEncoded())); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } /** * Returns a fingerprint string that returns the fingerprint using the * format n:n:n * * @param digest to create the hash value, please use SHA1 or MD5 only * */ private String getFingerPrint(String digest) { return (fingerprintBytesToStr(this.getFingerPrintBytes(digest))); } /** * Returns the cert path for this certificate as it exists in the keystore * * @return null if no cert path could be found */ public PKIXCertPathBuilderResult getPKIXCertPathBuilderResult(KeyStore keystore, List<X509Certificate> certificateList) { try { X509CertSelector selector = new X509CertSelector(); selector.setCertificate(this.getX509Certificate()); boolean selected = selector.match(this.getX509Certificate()); if (!selected) { return (null); } CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); PKIXBuilderParameters pkix = new PKIXBuilderParameters(keystore, selector); pkix.setRevocationEnabled(false); CertStoreParameters params = new CollectionCertStoreParameters(certificateList); CertStore certstore = CertStore.getInstance("Collection", params, "BC"); pkix.addCertStore(certstore); PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder .build((PKIXBuilderParameters) pkix); return (result); } catch (NoSuchProviderException e) { } catch (KeyStoreException e) { } catch (NoSuchAlgorithmException e) { } catch (InvalidAlgorithmParameterException e) { } catch (CertPathBuilderException e) { } return (null); } /** * Validates the certificate and returns the trust anchor certificate if the * cert path is valid and the full path could be validated * * @return null if the certificate could not be trusted or an other failure * like nosuchalg exception etc occurs */ public X509Certificate validateCertPath(KeyStore keystore, List<X509Certificate> certificateList) { CertPath certPath = this.getPKIXCertPathBuilderResult(keystore, certificateList).getCertPath(); if (certPath == null) { return (null); } try { // Validator params PKIXParameters params = new PKIXParameters(keystore); // Disable CRL checking since we are not supplying any CRLs params.setRevocationEnabled(false); //use BC here else PKCS#12 is not supported as keystore CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", "BC"); CertPathValidatorResult result = certPathValidator.validate(certPath, params); // Get the CA used to validate this path PKIXCertPathValidatorResult pkixResult = (PKIXCertPathValidatorResult) result; TrustAnchor ta = pkixResult.getTrustAnchor(); X509Certificate taCert = ta.getTrustedCert(); return (taCert); } catch (NoSuchProviderException e) { } catch (KeyStoreException e) { } catch (NoSuchAlgorithmException e) { } catch (InvalidAlgorithmParameterException e) { } catch (CertPathValidatorException e) { // Validation failed } return (null); } @Override public String toString() { return (this.alias); } @Override public int compareTo(Object object) { if (this.equals(object)) { return (0); } KeystoreCertificate otherCert = (KeystoreCertificate) object; return (this.alias.toUpperCase().compareTo(otherCert.alias.toUpperCase())); } /** * Returns a string that contains information about the certificate */ public String getInfo() { DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT); StringBuilder infoText = new StringBuilder(); infoText.append("Version: ").append(this.getVersion()); if (this.isRootCertificate()) { infoText.append(" (Root certificate)"); } infoText.append("\n"); infoText.append("Subject: ").append(this.getSubjectDN()).append("\n"); infoText.append("Issuer: ").append(this.getIssuerDN()).append("\n"); infoText.append("Serial (dec): ").append(this.getSerialNumberDEC()).append("\n"); infoText.append("Serial (hex): ").append(this.getSerialNumberHEX()).append("\n"); infoText.append("Valid from: ").append(format.format(this.getNotBefore())).append("\n"); infoText.append("Valid until: ").append(format.format(this.getNotAfter())).append("\n"); infoText.append("Public key: ").append(this.getPublicKeyLength()).append(" ") .append(this.getPublicKeyAlgorithm()).append("\n"); infoText.append("Signature algorithm: ").append(this.getSigAlgName()).append("\n"); try { infoText.append("Fingerprint (MD5): ").append(this.getFingerPrintMD5()).append("\n"); infoText.append("Fingerprint (SHA-1): ").append(this.getFingerPrintSHA1()).append("\n"); } catch (Exception e) { infoText.append("Fingerprint processing failed: ").append(e.getMessage()); } return (infoText.toString()); } /** * Returns some information about the certificate extensions */ public String getInfoExtension() { StringBuilder extensionText = new StringBuilder(); List<String> crl = this.getCrlDistributionURLs(); for (int i = 0; i < crl.size(); i++) { extensionText.append("CRL distribution[").append(String.valueOf(i + 1)).append("]: ").append(crl.get(i)) .append("\n"); } List<String> alternativeNames = this.getSubjectAlternativeNames(); if (alternativeNames.size() > 0) { extensionText.append("Subject alternative name: ").append(this.convertListToString(alternativeNames)) .append("\n"); } List<String> keyUsages = this.getKeyUsages(); if (keyUsages.size() > 0) { extensionText.append("Key usage: ").append(this.convertListToString(keyUsages)).append("\n"); } List<String> extkeyUsages = this.getExtendedKeyUsage(); if (extkeyUsages.size() > 0) { extensionText.append("Extended key usage: ").append(this.convertListToString(extkeyUsages)) .append("\n"); } List<String> authorityKeyIdentifier = this.getAuthorityKeyIdentifier(); if (authorityKeyIdentifier.size() > 0) { extensionText.append("Authority key identifier: ") .append(this.convertListToString(authorityKeyIdentifier)).append("\n"); } List<String> subjectKeyIdentifier = this.getSubjectKeyIdentifier(); if (subjectKeyIdentifier.size() > 0) { extensionText.append("Subject key identifier: ").append(this.convertListToString(subjectKeyIdentifier)) .append("\n"); } return (extensionText.toString()); } /** * Converts the arraylist content to a comma separated string */ private String convertListToString(Collection<String> list) { StringBuilder builder = new StringBuilder(); for (String value : list) { if (builder.length() > 0) { builder.append(", "); } builder.append(value); } return (builder.toString()); } /** * Overwrite the equal method of object * * @param anObject object ot compare */ @Override public boolean equals(Object anObject) { if (anObject == this) { return (true); } if (anObject != null && anObject instanceof KeystoreCertificate) { KeystoreCertificate cert = (KeystoreCertificate) anObject; String otherFingerPrint = null; String ownFingerPrint = null; try { otherFingerPrint = cert.getFingerPrintSHA1(); ownFingerPrint = this.getFingerPrintSHA1(); return (otherFingerPrint.equals(ownFingerPrint)); } catch (Exception e) { //unable to obtain the finger print. Use the serial number and the dates. return (cert.getIssuerDN().equals(this.getIssuerDN()) && cert.getNotAfter().equals(this.getNotAfter()) && cert.getNotBefore().equals(this.getNotBefore())); } } return (false); } @Override public int hashCode() { int hash = 7; hash = 97 * hash + (this.alias != null ? this.alias.hashCode() : 0); hash = 97 * hash + (this.certificate != null ? this.certificate.hashCode() : 0); hash = 97 * hash + (this.isKeyPair ? 1 : 0); return hash; } /** * '3D:A0:27:42:4D:92:6D:04:BB:74:66:1D:48:3E:61:6A:46:2A:05:B7' */ // public static final void main(String[] args) { // byte[] test = new byte[]{ // (byte) 0x00, (byte) 0x3D, (byte)0x04 , (byte) 0xA0, (byte) 0x92, // (byte) 0x6D, (byte) 0x6D, (byte) 0x04, (byte) 0xBB, (byte) 0x74, // (byte) 0x66, (byte) 0x1D, (byte) 0x48, (byte) 0x3E, (byte) 0x61, // (byte) 0x6A, (byte) 0x46, (byte) 0x05, (byte) 0xB7, (byte) 0x42, // }; // String str = KeystoreCertificate.fingerprintBytesToStr(test); // byte[] testbytes = KeystoreCertificate.fingerprintStrToBytes(str); // boolean areequal = Arrays.equals(test, testbytes); // System.out.println(areequal); // } }