📄 certificatemanager.java
字号:
* @return true if a certificate with the specifed configuration was found in the key store. * @throws KeyStoreException */ private static boolean isCertificate(KeyStore ksKeys, String domain, String algorithm) throws KeyStoreException { for (Enumeration<String> aliases = ksKeys.aliases(); aliases.hasMoreElements();) { X509Certificate certificate = (X509Certificate) ksKeys.getCertificate(aliases.nextElement()); if ("*".equals(domain)) { // Any domain certified by the certificate is accepted if (certificate.getPublicKey().getAlgorithm().equals(algorithm)) { return true; } } else { // Only accept certified domains that match the specified domain for (String identity : getPeerIdentities(certificate)) { if (identity.endsWith(domain) && certificate.getPublicKey().getAlgorithm().equals(algorithm)) { return true; } } } } return false; } /** * Returns true if the specified certificate is a self-signed certificate. * * @param keyStore key store that holds the certificate to verify. * @param alias alias of the certificate in the key store. * @return true if the specified certificate is a self-signed certificate. * @throws KeyStoreException if an error happens while usign the keystore */ public static boolean isSelfSignedCertificate(KeyStore keyStore, String alias) throws KeyStoreException { // Get certificate chain java.security.cert.Certificate[] certificateChain = keyStore.getCertificateChain(alias); // Verify that the chain is empty or was signed by himself return certificateChain == null || certificateChain.length == 1; } /** * Returns true if the specified certificate is ready to be signed by a Certificate Authority. Self-signed * certificates need to get their issuer information entered to be able to generate a Certificate * Signing Request (CSR). * * @param keyStore key store that holds the certificate to verify. * @param alias alias of the certificate in the key store. * @return true if the specified certificate is ready to be signed by a Certificate Authority. * @throws KeyStoreException if an error happens while usign the keystore */ public static boolean isSigningRequestPending(KeyStore keyStore, String alias) throws KeyStoreException { // Verify that this is a self-signed certificate if (!isSelfSignedCertificate(keyStore, alias)) { return false; } // Verify that the issuer information has been entered X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); Matcher matcher = valuesPattern.matcher(certificate.getIssuerDN().toString()); return matcher.find() && matcher.find(); } /** * Creates and returns the content of a new singing request for the specified certificate. Signing * requests are required by Certificate Authorities as part of their signing process. The signing request * contains information about the certificate issuer, subject DN, subject alternative names and public key. * Private keys are not included. After the Certificate Authority verified and signed the certificate a new * certificate is going to be returned. Use {@link #installReply(java.security.KeyStore, java.security.KeyStore, String, String, java.io.InputStream, boolean, boolean)} * to import the CA reply. * * @param cert the certificate to create a signing request. * @param privKey the private key of the certificate. * @return the content of a new singing request for the specified certificate. * @throws Exception */ public static String createSigningRequest(X509Certificate cert, PrivateKey privKey) throws Exception { StringBuilder sb = new StringBuilder(); String subject = cert.getSubjectDN().getName(); X509Name xname = new X509Name(subject); PublicKey pubKey = cert.getPublicKey(); String signatureAlgorithm = "DSA".equals(pubKey.getAlgorithm()) ? "SHA1withDSA" : "MD5withRSA"; PKCS10CertificationRequest csr = new PKCS10CertificationRequest(signatureAlgorithm, xname, pubKey, null, privKey); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DEROutputStream deros = new DEROutputStream(baos); deros.writeObject(csr.getDERObject()); String sTmp = new String(org.bouncycastle.util.encoders.Base64.encode(baos.toByteArray())); // Header sb.append("-----BEGIN NEW CERTIFICATE REQUEST-----\n"); // Add signing request content (base 64 encoded) for (int iCnt = 0; iCnt < sTmp.length(); iCnt += CERT_REQ_LINE_LENGTH) { int iLineLength; if ((iCnt + CERT_REQ_LINE_LENGTH) > sTmp.length()) { iLineLength = sTmp.length() - iCnt; } else { iLineLength = CERT_REQ_LINE_LENGTH; } sb.append(sTmp.substring(iCnt, iCnt + iLineLength)).append("\n"); } // Footer sb.append("-----END NEW CERTIFICATE REQUEST-----\n"); return sb.toString(); } /** * Installs the Certificate Authority reply returned as part of the signing request. The certificate * being signed will get its certificate chain updated with the imported certificate(s). An exception * will be thrown if the replied certificate does not match a local certificate or if the signing * authority is not known by the server (i.e. keystore and truststore files). When <tt>trustCACerts</tt> * is set to <tt>true</tt> then certificates present in the truststore file will be used to verify the * identity of the entity signing the certificate. In case the reply is composed of more than one * certificate then you can also specify if you want to verify that the root certificate in the chain * can be trusted. * * @param keyStore key store where the certificate is stored. * @param trustStore key store where ca certificates are stored. * @param keyPassword password of the keystore. * @param alias the alias of the existing certificate being signed. * @param inputStream the stream containing the CA reply. * @param trustCACerts true if certificates present in the truststore file will be used to verify the * identity of the entity signing the certificate. * @param validateRoot true if you want to verify that the root certificate in the chain can be trusted * based on the truststore. * @return true if the CA reply was successfully processed. * @throws Exception */ public static boolean installReply(KeyStore keyStore, KeyStore trustStore, String keyPassword, String alias, InputStream inputStream, boolean trustCACerts, boolean validateRoot) throws Exception { // Check that there is a certificate for the specified alias X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); if (certificate == null) { Log.warn("Certificate not found for alias: " + alias); return false; } // Retrieve the private key of the stored certificate PrivateKey privKey = (PrivateKey) keyStore.getKey(alias, keyPassword.toCharArray()); // Load certificates found in the PEM input stream List<X509Certificate> certs = new ArrayList<X509Certificate>(); for (Certificate cert : CertificateFactory.getInstance("X509").generateCertificates(inputStream)) { certs.add((X509Certificate) cert); } if (certs.isEmpty()) { throw new Exception("Reply has no certificates"); } List<X509Certificate> newCerts; if (certs.size() == 1) { // Reply has only one certificate newCerts = establishCertChain(keyStore, trustStore, null, certs.get(0), trustCACerts); } else { // Reply has a chain of certificates newCerts = validateReply(keyStore, trustStore, alias, null, certs, trustCACerts, validateRoot); } if (newCerts != null) { keyStore.setKeyEntry(alias, privKey, keyPassword.toCharArray(), newCerts.toArray(new X509Certificate[newCerts.size()])); // Notify listeners that a new certificate has been created for (CertificateEventListener listener : listeners) { try { listener.certificateSigned(keyStore, alias, newCerts); } catch (Exception e) { Log.error(e); } } return true; } else { return false; } } /** * Imports a new signed certificate and its private key into the keystore. The certificate input * stream may contain the signed certificate as well as its CA chain. * * @param keyStore key store where the certificate will be stored. * @param trustStore key store where ca certificates are stored. * @param keyPassword password of the keystore. * @param alias the alias of the the new signed certificate. * @param pkInputStream the stream containing the private key. * @param passPhrase is the password phrased used when creating the private key. * @param inputStream the stream containing the signed certificate. * @param trustCACerts true if certificates present in the truststore file will be used to verify the * identity of the entity signing the certificate. * @param validateRoot true if you want to verify that the root certificate in the chain can be trusted * based on the truststore. * @return true if the certificate was successfully imported. * @throws Exception if no certificates were found in the inputStream. */ public static boolean installCert(KeyStore keyStore, KeyStore trustStore, String keyPassword, String alias, InputStream pkInputStream, final String passPhrase, InputStream inputStream, boolean trustCACerts, boolean validateRoot) throws Exception { // Check that there is a certificate for the specified alias X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); if (certificate != null) { Log.warn("Certificate already exists for alias: " + alias); return false; } // Retrieve the private key of the stored certificate PasswordFinder passwordFinder = new PasswordFinder() { public char[] getPassword() { return passPhrase != null ? passPhrase.toCharArray() : new char[] {}; } }; PEMReader pemReader = new PEMReader(new InputStreamReader(pkInputStream), passwordFinder); KeyPair kp = (KeyPair) pemReader.readObject(); PrivateKey privKey = kp.getPrivate(); // Load certificates found in the PEM input stream List<X509Certificate> certs = new ArrayList<X509Certificate>(); for (Certificate cert : CertificateFactory.getInstance("X509").generateCertificates(inputStream)) { certs.add((X509Certificate) cert); } if (certs.isEmpty()) { throw new Exception("No certificates were found"); } List<X509Certificate> newCerts; if (certs.size() == 1) { // Reply has only one certificate newCerts = establishCertChain(keyStore, trustStore, certificate, certs.get(0), trustCACerts); } else { // Reply has a chain of certificates newCerts = validateReply(keyStore, trustStore, alias, certificate, certs, trustCACerts, validateRoot); } if (newCerts != null) { keyStore.setKeyEntry(alias, privKey, keyPassword.toCharArray(), newCerts.toArray(new X509Certificate[newCerts.size()])); // Notify listeners that a new certificate has been created (and signed) for (CertificateEventListener listener : listeners) { try { listener.certificateCreated(keyStore, alias, certs.get(0)); if (newCerts.size() > 1) { listener.certificateSigned(keyStore, alias, newCerts); } } catch (Exception e) { Log.error(e); } } return true; } else { return false; } } /** * Registers a listener to receive events. * * @param listener the listener. */ public static void addListener(CertificateEventListener listener) { if (listener == null) { throw new NullPointerException(); } listeners.add(listener); } /** * Unregisters a listener to receive events. * * @param listener the listener. */ public static void removeListener(CertificateEventListener listener) { listeners.remove(listener); } private static List<X509Certificate> establishCertChain(KeyStore keyStore, KeyStore trustStore, X509Certificate certificate, X509Certificate certReply, boolean trustCACerts) throws Exception { if (certificate != null) { PublicKey publickey = certificate.getPublicKey(); PublicKey publickey1 = certReply.getPublicKey();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -