@Override public KeyManager[] getKeyManagers(KeyStore keyStore, String keyStorePassword) { return KeyStoreUtil.getKeyManagers(keyStore, keyStorePassword, null, null); } }
@Override public SslContext get() { return SslUtil.getUpstreamServerSslContext(serverCipherSuites, trustSource); } });
/** * Creates a signature algorithm string using the specified message digest and the encryption type corresponding * to the supplied signingKey. Useful when generating the signature algorithm to be used to sign server certificates * using the CA root certificate's signingKey. * <p/> * For example, if the root certificate has an RSA private key, and you * wish to use the SHA256 message digest, this method will return the string "SHA256withRSA". See the * "Signature Algorithms" section of http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html * for a list of JSSE-supported signature algorithms. * * @param messageDigest digest to use to sign the certificate, such as SHA512 * @param signingKey private key that will be used to sign the certificate * @return a JCA-compatible signature algorithm */ public static String getSignatureAlgorithm(String messageDigest, Key signingKey) { return messageDigest + "with" + getDigitalSignatureType(signingKey); }
@Override public List<String> get() { List<String> ciphers; if (OpenSsl.isAvailable()) { // TODO: consider switching to the list of all available ciphers using OpenSsl.availableCipherSuites() ciphers = getBuiltInCipherList(); } else { ciphers = getEnabledJdkCipherSuites(); if (ciphers.isEmpty()) { // could not retrieve the list of enabled ciphers from the JDK SSLContext, so use the hard-coded list ciphers = getBuiltInCipherList(); } } return ciphers; } });
String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, caPrivateKey); BigInteger serialNumber = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);
@Override public X509Certificate[] get() { try { // the file may contain UTF-8 characters, but the PEM-encoded certificate data itself must be US-ASCII String allCAs = ClasspathResourceUtil.classpathResourceToString(DEFAULT_TRUSTED_CA_RESOURCE, StandardCharsets.UTF_8); return readX509CertificatesFromPem(allCAs); } catch (UncheckedIOException e) { log.warn("Unable to load built-in trusted CAs; no built-in CAs will be trusted", e); return new X509Certificate[0]; } } });
/** * Saves the root certificate as PEM-encoded data to the specified file. */ public void saveRootCertificateAsPemFile(File file) { String pemEncodedCertificate = securityProviderTool.encodeCertificateAsPem(generatedCertificateAndKey.get().getCertificate()); EncryptionUtil.writePemStringToFile(file, pemEncodedCertificate); }
/** * Creates a new KeyStore containing the specified root certificate and private key. * * @param keyStoreType type of the generated KeyStore, such as PKCS12 or JKS * @param certificate root certificate to add to the KeyStore * @param privateKeyAlias alias for the private key in the KeyStore * @param privateKey private key to add to the KeyStore * @param privateKeyPassword password for the private key * @param provider JCA provider to use, or null to use the system default * @return new KeyStore containing the root certificate and private key */ public static KeyStore createRootCertificateKeyStore(String keyStoreType, X509Certificate certificate, String privateKeyAlias, PrivateKey privateKey, String privateKeyPassword, String provider) { if (privateKeyPassword == null) { throw new IllegalArgumentException("Must specify a KeyStore password"); } KeyStore newKeyStore = KeyStoreUtil.createEmptyKeyStore(keyStoreType, provider); try { newKeyStore.setKeyEntry(privateKeyAlias, privateKey, privateKeyPassword.toCharArray(), new Certificate[]{certificate}); } catch (KeyStoreException e) { throw new KeyStoreAccessException("Unable to store certificate and private key in KeyStore", e); } return newKeyStore; }
@Override public X509Certificate[] get() { X509TrustManager defaultTrustManager = getDefaultJavaTrustManager(); X509Certificate[] defaultJavaTrustedCerts = defaultTrustManager.getAcceptedIssuers(); if (defaultJavaTrustedCerts != null) { return defaultJavaTrustedCerts; } else { return EMPTY_CERTIFICATE_ARRAY; } } });
public ImpersonatingMitmManager build() { if (clientCiphers == null) { clientCiphers = SslUtil.getDefaultCipherList(); } if (serverCiphers == null) { serverCiphers = SslUtil.getDefaultCipherList(); } return new ImpersonatingMitmManager( rootCertificateSource, serverKeyGenerator, serverMessageDigest, trustSource, cacheConcurrencyLevel, cacheExpirationIntervalMs, securityProviderTool, certificateInfoGenerator, serverCiphers, clientCiphers ); } }
/** * Returns a TrustSource containing only the builtin trusted CAs and does not include the JVM's trusted CAs. * See {@link TrustUtil#getBuiltinTrustedCAs()}. */ public static TrustSource builtinTrustSource() { return new TrustSource(TrustUtil.getBuiltinTrustedCAs()); }
/** * Returns a TrustSource containing the default CAs trusted by this JVM. See {@link TrustUtil#getJavaTrustedCAs()}. */ public static TrustSource javaTrustSource() { return new TrustSource(TrustUtil.getJavaTrustedCAs()); }
/** * Parses a String containing zero or more PEM-encoded X509 certificates into an array of {@link X509Certificate}. * Everything outside of BEGIN CERTIFICATE and END CERTIFICATE lines will be ignored. * * @param pemEncodedCAs a String containing PEM-encoded certficiates * @return array containing certificates in the String */ public static X509Certificate[] readX509CertificatesFromPem(String pemEncodedCAs) { List<X509Certificate> certificates = new ArrayList<>(500); Matcher pemMatcher = CA_PEM_PATTERN.matcher(pemEncodedCAs); while (pemMatcher.find()) { String singleCAPem = pemMatcher.group(); X509Certificate certificate = readSingleX509Certificate(singleCAPem); certificates.add(certificate); } return certificates.toArray(new X509Certificate[0]); }
@Override public KeyStore createRootCertificateKeyStore(String keyStoreType, CertificateAndKey rootCertificateAndKey, String privateKeyAlias, String password) { return KeyStoreUtil.createRootCertificateKeyStore(keyStoreType, rootCertificateAndKey.getCertificate(), privateKeyAlias, rootCertificateAndKey.getPrivateKey(), password, null); }
/** * Returns a new TrustSource containing the same trusted CAs as this TrustSource, plus all trusted certificate * entries from the specified trustStore. This method will only add trusted certificate entries from the specified * KeyStore (i.e. entries of type {@link java.security.KeyStore.TrustedCertificateEntry}; private keys will be * ignored. The trustStore may be in JKS or PKCS12 format. * * @param trustStore keystore containing trusted certificate entries * @return a new TrustSource containing this TrustSource's trusted CAs plus trusted certificate entries from the keystore */ public TrustSource add(KeyStore trustStore) { if (trustStore == null) { throw new IllegalArgumentException("Trust store cannot be null"); } List<X509Certificate> trustedCertificates = TrustUtil.extractTrustedCertificateEntries(trustStore); return add(trustedCertificates.toArray(new X509Certificate[0])); }
/** * Creates an SSLContext that will present an impersonated certificate for the specified hostname to the client. * This is a convenience method for {@link #createImpersonatingSslContext(CertificateInfo)} that generates the * {@link CertificateInfo} from the specified hostname using the {@link #certificateInfoGenerator}. * * @param sslSession sslSession between the proxy and the upstream server * @param hostnameToImpersonate hostname (supplied by the client's HTTP CONNECT) that will be impersonated * @return an SSLContext presenting a certificate matching the hostnameToImpersonate */ private SslContext createImpersonatingSslContext(SSLSession sslSession, String hostnameToImpersonate) { // get the upstream server's certificate so the certificateInfoGenerator can (optionally) use it to construct a forged certificate X509Certificate originalCertificate = SslUtil.getServerCertificate(sslSession); // get the CertificateInfo that will be used to populate the impersonated X509Certificate CertificateInfo certificateInfo = certificateInfoGenerator.generate(Collections.singletonList(hostnameToImpersonate), originalCertificate); SslContext sslContext = createImpersonatingSslContext(certificateInfo); return sslContext; }
private CertificateAndKey loadCertificateAndKeyFiles() { if (certificateFile == null) { throw new IllegalArgumentException("PEM root certificate file cannot be null"); } if (privateKeyFile == null) { throw new IllegalArgumentException("PEM private key file cannot be null"); } if (privateKeyPassword == null) { log.warn("Attempting to load private key from file without password. Private keys should be password-protected."); } String pemEncodedCertificate = EncryptionUtil.readPemStringFromFile(certificateFile); X509Certificate certificate = securityProviderTool.decodePemEncodedCertificate(new StringReader(pemEncodedCertificate)); String pemEncodedPrivateKey = EncryptionUtil.readPemStringFromFile(privateKeyFile); PrivateKey privateKey = securityProviderTool.decodePemEncodedPrivateKey(new StringReader(pemEncodedPrivateKey), privateKeyPassword); return new CertificateAndKey(certificate, privateKey); } }
/** * Returns a new TrustSource containing the same trusted CAs as this TrustSource, plus zero or more CAs contained in * the PEM-encoded String. The String may contain multiple certificates and may contain comments or other non-PEM-encoded * text, as long as the PEM-encoded certificates are delimited by appropriate BEGIN_CERTIFICATE and END_CERTIFICATE * text blocks. * * @param trustedPemEncodedCAs String containing PEM-encoded certificates to trust * @return a new TrustSource containing this TrustSource's trusted CAs plus the CAs in the specified String */ public TrustSource add(String trustedPemEncodedCAs) { if (trustedPemEncodedCAs == null) { throw new IllegalArgumentException("PEM-encoded trusted CA String cannot be null"); } X509Certificate[] trustedCertificates = TrustUtil.readX509CertificatesFromPem(trustedPemEncodedCAs); return add(trustedCertificates); }
/** * Saves the private key as PEM-encoded data to a file, using the specified password to encrypt the private key and * the {@link #DEFAULT_PEM_ENCRYPTION_ALGORITHM}. If the password is null, the private key will be stored unencrypted. * In general, private keys should not be stored unencrypted. * * @param file file to save the private key to * @param passwordForPrivateKey password to protect the private key */ public void savePrivateKeyAsPemFile(File file, String passwordForPrivateKey) { String pemEncodedPrivateKey = securityProviderTool.encodePrivateKeyAsPem(generatedCertificateAndKey.get().getPrivateKey(), passwordForPrivateKey, DEFAULT_PEM_ENCRYPTION_ALGORITHM); EncryptionUtil.writePemStringToFile(file, pemEncodedPrivateKey); }
@Override public KeyStore createServerKeyStore(String keyStoreType, CertificateAndKey serverCertificateAndKey, X509Certificate rootCertificate, String privateKeyAlias, String password) { if (password == null) { throw new IllegalArgumentException("KeyStore password cannot be null"); } if (privateKeyAlias == null) { throw new IllegalArgumentException("Private key alias cannot be null"); } // create a KeyStore containing the impersonated certificate's private key and a certificate chain with the // impersonated cert and our root certificate KeyStore impersonatedCertificateKeyStore = KeyStoreUtil.createEmptyKeyStore(keyStoreType, null); // create the certificate chain back for the impersonated certificate back to the root certificate Certificate[] chain = {serverCertificateAndKey.getCertificate(), rootCertificate}; try { // place the impersonated certificate and its private key in the KeyStore impersonatedCertificateKeyStore.setKeyEntry(privateKeyAlias, serverCertificateAndKey.getPrivateKey(), password.toCharArray(), chain); } catch (KeyStoreException e) { throw new KeyStoreAccessException("Error storing impersonated certificate and private key in KeyStore", e); } return impersonatedCertificateKeyStore; }