package net.lightbody.bmp.mitm; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import net.lightbody.bmp.mitm.tools.DefaultSecurityProviderTool; import net.lightbody.bmp.mitm.tools.SecurityProviderTool; import net.lightbody.bmp.mitm.util.EncryptionUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.StringReader; import java.security.PrivateKey; import java.security.cert.X509Certificate; /** * Loads impersonation materials from two separate, PEM-encoded files: a CA root certificate and its corresponding * private key. */ public class PemFileCertificateSource implements CertificateAndKeySource { private static final Logger log = LoggerFactory.getLogger(PemFileCertificateSource.class); private final File certificateFile; private final File privateKeyFile; private final String privateKeyPassword; private SecurityProviderTool securityProviderTool = new DefaultSecurityProviderTool(); private final Supplier<CertificateAndKey> certificateAndKey = Suppliers.memoize(new Supplier<CertificateAndKey>() { @Override public CertificateAndKey get() { return loadCertificateAndKeyFiles(); } }); /** * Creates a {@link CertificateAndKeySource} that loads the certificate and private key from PEM files. * * @param certificateFile PEM-encoded file containing the root certificate * @param privateKeyFile PEM-encoded file continaing the certificate's private key * @param privateKeyPassword password for the private key */ public PemFileCertificateSource(File certificateFile, File privateKeyFile, String privateKeyPassword) { this.certificateFile = certificateFile; this.privateKeyFile = privateKeyFile; this.privateKeyPassword = privateKeyPassword; } /** * Override the default {@link SecurityProviderTool} used to load the PEM files. */ public PemFileCertificateSource certificateTool(SecurityProviderTool securityProviderTool) { this.securityProviderTool = securityProviderTool; return this; } @Override public CertificateAndKey load() { return certificateAndKey.get(); } 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); } }