net.lightbody.bmp.mitm.CertificateInfo Java Examples

The following examples show how to use net.lightbody.bmp.mitm.CertificateInfo. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ImpersonatingMitmManager.java    From CapturePacket with MIT License 5 votes vote down vote up
/**
 * 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;
}
 
Example #2
Source File: BouncyCastleSecurityProviderTool.java    From CapturePacket with MIT License 5 votes vote down vote up
/**
 * Creates an X500Name based on the specified certificateInfo.
 *
 * @param certificateInfo information to populate the X500Name with
 * @return a new X500Name object for use as a subject or issuer
 */
private static X500Name createX500NameForCertificate(CertificateInfo certificateInfo) {
    X500NameBuilder x500NameBuilder = new X500NameBuilder(BCStyle.INSTANCE);

    if (certificateInfo.getCommonName() != null) {
        x500NameBuilder.addRDN(BCStyle.CN, certificateInfo.getCommonName());
    }

    if (certificateInfo.getOrganization() != null) {
        x500NameBuilder.addRDN(BCStyle.O, certificateInfo.getOrganization());
    }

    if (certificateInfo.getOrganizationalUnit() != null) {
        x500NameBuilder.addRDN(BCStyle.OU, certificateInfo.getOrganizationalUnit());
    }

    if (certificateInfo.getEmail() != null) {
        x500NameBuilder.addRDN(BCStyle.E, certificateInfo.getEmail());
    }

    if (certificateInfo.getLocality() != null) {
        x500NameBuilder.addRDN(BCStyle.L, certificateInfo.getLocality());
    }

    if (certificateInfo.getState() != null) {
        x500NameBuilder.addRDN(BCStyle.ST, certificateInfo.getState());
    }

    if (certificateInfo.getCountryCode() != null) {
        x500NameBuilder.addRDN(BCStyle.C, certificateInfo.getCountryCode());
    }

    // TODO: Add more X.509 certificate fields as needed

    return x500NameBuilder.build();
}
 
Example #3
Source File: BouncyCastleSecurityProviderTool.java    From AndroidHttpCapture with MIT License 5 votes vote down vote up
/**
 * Creates an X500Name based on the specified certificateInfo.
 *
 * @param certificateInfo information to populate the X500Name with
 * @return a new X500Name object for use as a subject or issuer
 */
private static X500Name createX500NameForCertificate(CertificateInfo certificateInfo) {
    X500NameBuilder x500NameBuilder = new X500NameBuilder(BCStyle.INSTANCE);

    if (certificateInfo.getCommonName() != null) {
        x500NameBuilder.addRDN(BCStyle.CN, certificateInfo.getCommonName());
    }

    if (certificateInfo.getOrganization() != null) {
        x500NameBuilder.addRDN(BCStyle.O, certificateInfo.getOrganization());
    }

    if (certificateInfo.getOrganizationalUnit() != null) {
        x500NameBuilder.addRDN(BCStyle.OU, certificateInfo.getOrganizationalUnit());
    }

    if (certificateInfo.getEmail() != null) {
        x500NameBuilder.addRDN(BCStyle.E, certificateInfo.getEmail());
    }

    if (certificateInfo.getLocality() != null) {
        x500NameBuilder.addRDN(BCStyle.L, certificateInfo.getLocality());
    }

    if (certificateInfo.getState() != null) {
        x500NameBuilder.addRDN(BCStyle.ST, certificateInfo.getState());
    }

    if (certificateInfo.getCountryCode() != null) {
        x500NameBuilder.addRDN(BCStyle.C, certificateInfo.getCountryCode());
    }

    // TODO: Add more X.509 certificate fields as needed

    return x500NameBuilder.build();
}
 
Example #4
Source File: ImpersonatingMitmManager.java    From Dream-Catcher with MIT License 5 votes vote down vote up
/**
 * 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;
}
 
Example #5
Source File: ImpersonatingMitmManager.java    From AndroidHttpCapture with MIT License 5 votes vote down vote up
/**
 * 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;
}
 
Example #6
Source File: BouncyCastleSecurityProviderTool.java    From Dream-Catcher with MIT License 5 votes vote down vote up
/**
 * Creates an X500Name based on the specified certificateInfo.
 *
 * @param certificateInfo information to populate the X500Name with
 * @return a new X500Name object for use as a subject or issuer
 */
private static X500Name createX500NameForCertificate(CertificateInfo certificateInfo) {
    X500NameBuilder x500NameBuilder = new X500NameBuilder(BCStyle.INSTANCE);

    if (certificateInfo.getCommonName() != null) {
        x500NameBuilder.addRDN(BCStyle.CN, certificateInfo.getCommonName());
    }

    if (certificateInfo.getOrganization() != null) {
        x500NameBuilder.addRDN(BCStyle.O, certificateInfo.getOrganization());
    }

    if (certificateInfo.getOrganizationalUnit() != null) {
        x500NameBuilder.addRDN(BCStyle.OU, certificateInfo.getOrganizationalUnit());
    }

    if (certificateInfo.getEmail() != null) {
        x500NameBuilder.addRDN(BCStyle.E, certificateInfo.getEmail());
    }

    if (certificateInfo.getLocality() != null) {
        x500NameBuilder.addRDN(BCStyle.L, certificateInfo.getLocality());
    }

    if (certificateInfo.getState() != null) {
        x500NameBuilder.addRDN(BCStyle.ST, certificateInfo.getState());
    }

    if (certificateInfo.getCountryCode() != null) {
        x500NameBuilder.addRDN(BCStyle.C, certificateInfo.getCountryCode());
    }

    // TODO: Add more X.509 certificate fields as needed

    return x500NameBuilder.build();
}
 
Example #7
Source File: ImpersonatingMitmManager.java    From CapturePacket with MIT License 4 votes vote down vote up
/**
 * Generates an {@link SslContext} using an impersonated certificate containing the information in the specified
 * certificateInfo.
 *
 * @param certificateInfo certificate information to impersonate
 * @return an SslContext that will present the impersonated certificate to the client
 */
private SslContext createImpersonatingSslContext(CertificateInfo certificateInfo) {
    long impersonationStart = System.currentTimeMillis();

    // generate a public and private key pair for the forged certificate. the SslContext will send the impersonated certificate to clients
    // to impersonate the real upstream server, and will use the private key to encrypt the channel.
    KeyPair serverKeyPair = serverKeyGenerator.generate();

    // get the CA root certificate and private key that will be used to sign the forged certificate
    X509Certificate caRootCertificate = rootCertificate.get().getCertificate();
    PrivateKey caPrivateKey = rootCertificate.get().getPrivateKey();
    if (caRootCertificate == null || caPrivateKey == null) {
        throw new IllegalStateException("A CA root certificate and private key are required to sign a server certificate. Root certificate was: "
                + caRootCertificate + ". Private key was: " + caPrivateKey);
    }

    // determine if the server private key was signed with an RSA private key. though TLS no longer requires the server
    // certificate to use the same private key type as the root certificate, Java bug JDK-8136442 prevents Java from creating a opening an SSL socket
    // if the CA and server certificates are not of the same type. see https://bugs.openjdk.java.net/browse/JDK-8136442
    // note this only applies to RSA CAs signing EC server certificates; Java seems to properly handle EC CAs signing
    // RSA server certificates.
    if (EncryptionUtil.isEcKey(serverKeyPair.getPrivate()) && EncryptionUtil.isRsaKey(caPrivateKey)) {
        log.warn("CA private key is an RSA key and impersonated server private key is an Elliptic Curve key. JDK bug 8136442 may prevent the proxy server from creating connections to clients due to 'no cipher suites in common'.");
    }

    // create the forged server certificate and sign it with the root certificate and private key
    CertificateAndKey impersonatedCertificateAndKey = securityProviderTool.createServerCertificate(
            certificateInfo,
            caRootCertificate,
            caPrivateKey,
            serverKeyPair,
            serverCertificateMessageDigest);

    X509Certificate[] certChain = {impersonatedCertificateAndKey.getCertificate(), caRootCertificate};
    SslContext sslContext;
    try {
        sslContext = SslContextBuilder.forServer(impersonatedCertificateAndKey.getPrivateKey(), certChain)
                .ciphers(clientCipherSuites, SupportedCipherSuiteFilter.INSTANCE)
                .build();

    } catch (SSLException e) {
        throw new MitmException("Error creating SslContext for connection to client using impersonated certificate and private key", e);
    }

    long impersonationFinish = System.currentTimeMillis();

    statistics.certificateCreated(impersonationStart, impersonationFinish);

    log.debug("Impersonated certificate for {} in {}ms", certificateInfo.getCommonName(), impersonationFinish - impersonationStart);

    return sslContext;
}
 
Example #8
Source File: DefaultSecurityProviderTool.java    From AndroidHttpCapture with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo, X509Certificate caRootCertificate, PrivateKey caPrivateKey, KeyPair serverKeyPair, String messageDigest) {
    return bouncyCastle.createServerCertificate(certificateInfo, caRootCertificate, caPrivateKey, serverKeyPair, messageDigest);
}
 
Example #9
Source File: DefaultSecurityProviderTool.java    From AndroidHttpCapture with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo, KeyPair keyPair, String messageDigest) {
    return bouncyCastle.createCARootCertificate(certificateInfo, keyPair, messageDigest);
}
 
Example #10
Source File: BouncyCastleSecurityProviderTool.java    From AndroidHttpCapture with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                                 KeyPair keyPair,
                                                 String messageDigest) {
    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the X500Name that will be both the issuer and the subject of the new root certificate
    X500Name issuer = createX500NameForCertificate(certificateInfo);

    BigInteger serial = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    PublicKey rootCertificatePublicKey = keyPair.getPublic();

    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, keyPair.getPrivate());

    // this is a CA root certificate, so it is self-signed
    ContentSigner selfSigner = getCertificateSigner(keyPair.getPrivate(), signatureAlgorithm);

    ASN1EncodableVector extendedKeyUsages = new ASN1EncodableVector();
    extendedKeyUsages.add(KeyPurposeId.id_kp_serverAuth);
    extendedKeyUsages.add(KeyPurposeId.id_kp_clientAuth);
    extendedKeyUsages.add(KeyPurposeId.anyExtendedKeyUsage);

    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(
                issuer,
                serial,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                issuer,
                rootCertificatePublicKey)
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(rootCertificatePublicKey))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
                .addExtension(Extension.keyUsage, false, new KeyUsage(
                        KeyUsage.keyCertSign
                                | KeyUsage.digitalSignature
                                | KeyUsage.keyEncipherment
                                | KeyUsage.dataEncipherment
                                | KeyUsage.cRLSign))
                .addExtension(Extension.extendedKeyUsage, false, new DERSequence(extendedKeyUsages))
                .build(selfSigner);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating root certificate", e);
    }

    // convert the Bouncy Castle X590CertificateHolder to a JCA cert
    X509Certificate cert = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(cert, keyPair.getPrivate());
}
 
Example #11
Source File: BouncyCastleSecurityProviderTool.java    From AndroidHttpCapture with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                                 X509Certificate caRootCertificate,
                                                 PrivateKey caPrivateKey,
                                                 KeyPair serverKeyPair,
                                                 String messageDigest) {
    // make sure certificateInfo contains all fields necessary to generate the certificate
    if (certificateInfo.getCommonName() == null) {
        throw new IllegalArgumentException("Must specify CN for server certificate");
    }

    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the subject for the new server certificate. when impersonating an upstream server, this should contain
    // the hostname of the server we are trying to impersonate in the CN field
    X500Name serverCertificateSubject = createX500NameForCertificate(certificateInfo);

    // get the algorithm that will be used to sign the new certificate, which is a combination of the message digest
    // and the digital signature from the CA's private key
    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, caPrivateKey);

    // get a ContentSigner with our CA private key that will be used to sign the new server certificate
    ContentSigner signer = getCertificateSigner(caPrivateKey, signatureAlgorithm);

    // generate a serial number for the new certificate. serial numbers only need to be unique within our
    // certification authority; a large random integer will satisfy that requirement.
    BigInteger serialNumber = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    // create the X509Certificate using Bouncy Castle. the BC X509CertificateHolder can be converted to a JCA X509Certificate.
    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(caRootCertificate,
                serialNumber,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                serverCertificateSubject,
                serverKeyPair.getPublic())
                .addExtension(Extension.subjectAlternativeName, false, getDomainNameSANsAsASN1Encodable(certificateInfo.getSubjectAlternativeNames()))
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(serverKeyPair.getPublic()))
                .addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
                .build(signer);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating new server certificate", e);
    }

    // convert the Bouncy Castle certificate holder into a JCA X509Certificate
    X509Certificate serverCertificate = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(serverCertificate, serverKeyPair.getPrivate());
}
 
Example #12
Source File: ImpersonatingMitmManager.java    From AndroidHttpCapture with MIT License 4 votes vote down vote up
/**
 * Generates an {@link SslContext} using an impersonated certificate containing the information in the specified
 * certificateInfo.
 *
 * @param certificateInfo certificate information to impersonate
 * @return an SslContext that will present the impersonated certificate to the client
 */
private SslContext createImpersonatingSslContext(CertificateInfo certificateInfo) {
    long impersonationStart = System.currentTimeMillis();

    // generate a public and private key pair for the forged certificate. the SslContext will send the impersonated certificate to clients
    // to impersonate the real upstream server, and will use the private key to encrypt the channel.
    KeyPair serverKeyPair = serverKeyGenerator.generate();

    // get the CA root certificate and private key that will be used to sign the forged certificate
    X509Certificate caRootCertificate = rootCertificate.get().getCertificate();
    PrivateKey caPrivateKey = rootCertificate.get().getPrivateKey();
    if (caRootCertificate == null || caPrivateKey == null) {
        throw new IllegalStateException("A CA root certificate and private key are required to sign a server certificate. Root certificate was: "
                + caRootCertificate + ". Private key was: " + caPrivateKey);
    }

    // determine if the server private key was signed with an RSA private key. though TLS no longer requires the server
    // certificate to use the same private key type as the root certificate, Java bug JDK-8136442 prevents Java from creating a opening an SSL socket
    // if the CA and server certificates are not of the same type. see https://bugs.openjdk.java.net/browse/JDK-8136442
    // note this only applies to RSA CAs signing EC server certificates; Java seems to properly handle EC CAs signing
    // RSA server certificates.
    if (EncryptionUtil.isEcKey(serverKeyPair.getPrivate()) && EncryptionUtil.isRsaKey(caPrivateKey)) {
        log.warn("CA private key is an RSA key and impersonated server private key is an Elliptic Curve key. JDK bug 8136442 may prevent the proxy server from creating connections to clients due to 'no cipher suites in common'.");
    }

    // create the forged server certificate and sign it with the root certificate and private key
    CertificateAndKey impersonatedCertificateAndKey = securityProviderTool.createServerCertificate(
            certificateInfo,
            caRootCertificate,
            caPrivateKey,
            serverKeyPair,
            serverCertificateMessageDigest);

    X509Certificate[] certChain = {impersonatedCertificateAndKey.getCertificate(), caRootCertificate};
    SslContext sslContext;
    try {
        sslContext = SslContextBuilder.forServer(impersonatedCertificateAndKey.getPrivateKey(), certChain)
                .ciphers(clientCipherSuites, SupportedCipherSuiteFilter.INSTANCE)
                .build();

    } catch (SSLException e) {
        throw new MitmException("Error creating SslContext for connection to client using impersonated certificate and private key", e);
    }

    long impersonationFinish = System.currentTimeMillis();

    statistics.certificateCreated(impersonationStart, impersonationFinish);

    log.debug("Impersonated certificate for {} in {}ms", certificateInfo.getCommonName(), impersonationFinish - impersonationStart);

    return sslContext;
}
 
Example #13
Source File: DefaultSecurityProviderTool.java    From Dream-Catcher with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo, X509Certificate caRootCertificate, PrivateKey caPrivateKey, KeyPair serverKeyPair, String messageDigest) {
    return bouncyCastle.createServerCertificate(certificateInfo, caRootCertificate, caPrivateKey, serverKeyPair, messageDigest);
}
 
Example #14
Source File: DefaultSecurityProviderTool.java    From Dream-Catcher with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo, KeyPair keyPair, String messageDigest) {
    return bouncyCastle.createCARootCertificate(certificateInfo, keyPair, messageDigest);
}
 
Example #15
Source File: BouncyCastleSecurityProviderTool.java    From Dream-Catcher with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                                 KeyPair keyPair,
                                                 String messageDigest) {
    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the X500Name that will be both the issuer and the subject of the new root certificate
    X500Name issuer = createX500NameForCertificate(certificateInfo);

    BigInteger serial = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    PublicKey rootCertificatePublicKey = keyPair.getPublic();

    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, keyPair.getPrivate());

    // this is a CA root certificate, so it is self-signed
    ContentSigner selfSigner = getCertificateSigner(keyPair.getPrivate(), signatureAlgorithm);

    ASN1EncodableVector extendedKeyUsages = new ASN1EncodableVector();
    extendedKeyUsages.add(KeyPurposeId.id_kp_serverAuth);
    extendedKeyUsages.add(KeyPurposeId.id_kp_clientAuth);
    extendedKeyUsages.add(KeyPurposeId.anyExtendedKeyUsage);

    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(
                issuer,
                serial,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                issuer,
                rootCertificatePublicKey)
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(rootCertificatePublicKey))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
                .addExtension(Extension.keyUsage, false, new KeyUsage(
                        KeyUsage.keyCertSign
                                | KeyUsage.digitalSignature
                                | KeyUsage.keyEncipherment
                                | KeyUsage.dataEncipherment
                                | KeyUsage.cRLSign))
                .addExtension(Extension.extendedKeyUsage, false, new DERSequence(extendedKeyUsages))
                .build(selfSigner);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating root certificate", e);
    }

    // convert the Bouncy Castle X590CertificateHolder to a JCA cert
    X509Certificate cert = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(cert, keyPair.getPrivate());
}
 
Example #16
Source File: BouncyCastleSecurityProviderTool.java    From Dream-Catcher with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                                 X509Certificate caRootCertificate,
                                                 PrivateKey caPrivateKey,
                                                 KeyPair serverKeyPair,
                                                 String messageDigest) {
    // make sure certificateInfo contains all fields necessary to generate the certificate
    if (certificateInfo.getCommonName() == null) {
        throw new IllegalArgumentException("Must specify CN for server certificate");
    }

    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the subject for the new server certificate. when impersonating an upstream server, this should contain
    // the hostname of the server we are trying to impersonate in the CN field
    X500Name serverCertificateSubject = createX500NameForCertificate(certificateInfo);

    // get the algorithm that will be used to sign the new certificate, which is a combination of the message digest
    // and the digital signature from the CA's private key
    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, caPrivateKey);

    // get a ContentSigner with our CA private key that will be used to sign the new server certificate
    ContentSigner signer = getCertificateSigner(caPrivateKey, signatureAlgorithm);

    // generate a serial number for the new certificate. serial numbers only need to be unique within our
    // certification authority; a large random integer will satisfy that requirement.
    BigInteger serialNumber = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    // create the X509Certificate using Bouncy Castle. the BC X509CertificateHolder can be converted to a JCA X509Certificate.
    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(caRootCertificate,
                serialNumber,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                serverCertificateSubject,
                serverKeyPair.getPublic())
                .addExtension(Extension.subjectAlternativeName, false, getDomainNameSANsAsASN1Encodable(certificateInfo.getSubjectAlternativeNames()))
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(serverKeyPair.getPublic()))
                .addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
                .build(signer);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating new server certificate", e);
    }

    // convert the Bouncy Castle certificate holder into a JCA X509Certificate
    X509Certificate serverCertificate = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(serverCertificate, serverKeyPair.getPrivate());
}
 
Example #17
Source File: ImpersonatingMitmManager.java    From Dream-Catcher with MIT License 4 votes vote down vote up
/**
 * Generates an {@link SslContext} using an impersonated certificate containing the information in the specified
 * certificateInfo.
 *
 * @param certificateInfo certificate information to impersonate
 * @return an SslContext that will present the impersonated certificate to the client
 */
private SslContext createImpersonatingSslContext(CertificateInfo certificateInfo) {
    long impersonationStart = System.currentTimeMillis();

    // generate a public and private key pair for the forged certificate. the SslContext will send the impersonated certificate to clients
    // to impersonate the real upstream server, and will use the private key to encrypt the channel.
    KeyPair serverKeyPair = serverKeyGenerator.generate();

    // get the CA root certificate and private key that will be used to sign the forced certificate
    X509Certificate caRootCertificate = rootCertificate.get().getCertificate();
    PrivateKey caPrivateKey = rootCertificate.get().getPrivateKey();
    if (caRootCertificate == null || caPrivateKey == null) {
        throw new IllegalStateException("A CA root certificate and private key are required to sign a server certificate. Root certificate was: "
                + caRootCertificate + ". Private key was: " + caPrivateKey);
    }

    // determine if the server private key was signed with an RSA private key. though TLS no longer requires the server
    // certificate to use the same private key type as the root certificate, Java bug JDK-8136442 prevents Java from creating a opening an SSL socket
    // if the CA and server certificates are not of the same type. see https://bugs.openjdk.java.net/browse/JDK-8136442
    // note this only applies to RSA CAs signing EC server certificates; Java seems to properly handle EC CAs signing
    // RSA server certificates.
    if (EncryptionUtil.isEcKey(serverKeyPair.getPrivate()) && EncryptionUtil.isRsaKey(caPrivateKey)) {
        log.warn("CA private key is an RSA key and impersonated server private key is an Elliptic Curve key. JDK bug 8136442 may prevent the proxy server from creating connections to clients due to 'no cipher suites in common'.");
    }

    // create the forged server certificate and sign it with the root certificate and private key
    CertificateAndKey impersonatedCertificateAndKey = securityProviderTool.createServerCertificate(
            certificateInfo,
            caRootCertificate,
            caPrivateKey,
            serverKeyPair,
            serverCertificateMessageDigest);

    X509Certificate[] certChain = {impersonatedCertificateAndKey.getCertificate(), caRootCertificate};
    SslContext sslContext;
    try {
        sslContext = SslContextBuilder.forServer(impersonatedCertificateAndKey.getPrivateKey(), certChain)
                .ciphers(clientCipherSuites, SupportedCipherSuiteFilter.INSTANCE)
                .build();

    } catch (SSLException e) {
        throw new MitmException("Error creating SslContext for connection to client using impersonated certificate and private key", e);
    }

    long impersonationFinish = System.currentTimeMillis();

    statistics.certificateCreated(impersonationStart, impersonationFinish);

    log.debug("Impersonated certificate for {} in {}ms", certificateInfo.getCommonName(), impersonationFinish - impersonationStart);

    return sslContext;
}
 
Example #18
Source File: DefaultSecurityProviderTool.java    From CapturePacket with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo, X509Certificate caRootCertificate, PrivateKey caPrivateKey, KeyPair serverKeyPair, String messageDigest) {
    return bouncyCastle.createServerCertificate(certificateInfo, caRootCertificate, caPrivateKey, serverKeyPair, messageDigest);
}
 
Example #19
Source File: DefaultSecurityProviderTool.java    From CapturePacket with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo, KeyPair keyPair, String messageDigest) {
    return bouncyCastle.createCARootCertificate(certificateInfo, keyPair, messageDigest);
}
 
Example #20
Source File: BouncyCastleSecurityProviderTool.java    From CapturePacket with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                                 KeyPair keyPair,
                                                 String messageDigest) {
    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the X500Name that will be both the issuer and the subject of the new root certificate
    X500Name issuer = createX500NameForCertificate(certificateInfo);

    BigInteger serial = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    PublicKey rootCertificatePublicKey = keyPair.getPublic();

    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, keyPair.getPrivate());

    // this is a CA root certificate, so it is self-signed
    ContentSigner selfSigner = getCertificateSigner(keyPair.getPrivate(), signatureAlgorithm);

    ASN1EncodableVector extendedKeyUsages = new ASN1EncodableVector();
    extendedKeyUsages.add(KeyPurposeId.id_kp_serverAuth);
    extendedKeyUsages.add(KeyPurposeId.id_kp_clientAuth);
    extendedKeyUsages.add(KeyPurposeId.anyExtendedKeyUsage);

    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(
                issuer,
                serial,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                issuer,
                rootCertificatePublicKey)
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(rootCertificatePublicKey))
                .addExtension(Extension.basicConstraints, true, new BasicConstraints(true))
                .addExtension(Extension.keyUsage, false, new KeyUsage(
                        KeyUsage.keyCertSign
                                | KeyUsage.digitalSignature
                                | KeyUsage.keyEncipherment
                                | KeyUsage.dataEncipherment
                                | KeyUsage.cRLSign))
                .addExtension(Extension.extendedKeyUsage, false, new DERSequence(extendedKeyUsages))
                .build(selfSigner);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating root certificate", e);
    }

    // convert the Bouncy Castle X590CertificateHolder to a JCA cert
    X509Certificate cert = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(cert, keyPair.getPrivate());
}
 
Example #21
Source File: BouncyCastleSecurityProviderTool.java    From CapturePacket with MIT License 4 votes vote down vote up
@Override
public CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                                 X509Certificate caRootCertificate,
                                                 PrivateKey caPrivateKey,
                                                 KeyPair serverKeyPair,
                                                 String messageDigest) {
    // make sure certificateInfo contains all fields necessary to generate the certificate
    if (certificateInfo.getCommonName() == null) {
        throw new IllegalArgumentException("Must specify CN for server certificate");
    }

    if (certificateInfo.getNotBefore() == null) {
        throw new IllegalArgumentException("Must specify Not Before for server certificate");
    }

    if (certificateInfo.getNotAfter() == null) {
        throw new IllegalArgumentException("Must specify Not After for server certificate");
    }

    // create the subject for the new server certificate. when impersonating an upstream server, this should contain
    // the hostname of the server we are trying to impersonate in the CN field
    X500Name serverCertificateSubject = createX500NameForCertificate(certificateInfo);

    // get the algorithm that will be used to sign the new certificate, which is a combination of the message digest
    // and the digital signature from the CA's private key
    String signatureAlgorithm = EncryptionUtil.getSignatureAlgorithm(messageDigest, caPrivateKey);

    // get a ContentSigner with our CA private key that will be used to sign the new server certificate
    ContentSigner signer = getCertificateSigner(caPrivateKey, signatureAlgorithm);

    // generate a serial number for the new certificate. serial numbers only need to be unique within our
    // certification authority; a large random integer will satisfy that requirement.
    BigInteger serialNumber = EncryptionUtil.getRandomBigInteger(CERTIFICATE_SERIAL_NUMBER_SIZE);

    // create the X509Certificate using Bouncy Castle. the BC X509CertificateHolder can be converted to a JCA X509Certificate.
    X509CertificateHolder certificateHolder;
    try {
        certificateHolder = new JcaX509v3CertificateBuilder(caRootCertificate,
                serialNumber,
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                serverCertificateSubject,
                serverKeyPair.getPublic())
                .addExtension(Extension.subjectAlternativeName, false, getDomainNameSANsAsASN1Encodable(certificateInfo.getSubjectAlternativeNames()))
                .addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(serverKeyPair.getPublic()))
                .addExtension(Extension.basicConstraints, false, new BasicConstraints(false))
                .build(signer);
    } catch (CertIOException e) {
        throw new CertificateCreationException("Error creating new server certificate", e);
    }

    // convert the Bouncy Castle certificate holder into a JCA X509Certificate
    X509Certificate serverCertificate = convertToJcaCertificate(certificateHolder);

    return new CertificateAndKey(serverCertificate, serverKeyPair.getPrivate());
}
 
Example #22
Source File: SecurityProviderTool.java    From Dream-Catcher with MIT License 2 votes vote down vote up
/**
 * Creates a new self-signed CA root certificate, suitable for use signing new server certificates.
 *
 * @param certificateInfo certificate info to populate in the new root cert
 * @param keyPair         root certificate's public and private keys
 * @param messageDigest   digest to use when signing the new root certificate, such as SHA512
 * @return a new root certificate and private key
 */
CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                          KeyPair keyPair,
                                          String messageDigest);
 
Example #23
Source File: SecurityProviderTool.java    From Dream-Catcher with MIT License 2 votes vote down vote up
/**
 * Creates a new server X.509 certificate using the serverKeyPair. The new certificate will be populated with
 * information from the specified certificateInfo and will be signed using the specified caPrivateKey and messageDigest.
 *
 * @param certificateInfo   basic X.509 certificate info that will be used to create the server certificate
 * @param caRootCertificate root certificate that will be used to populate the issuer field of the server certificate
 * @param serverKeyPair     server's public and private keys
 * @param messageDigest     message digest to use when signing the server certificate, such as SHA512
 * @param caPrivateKey      root certificate private key that will be used to sign the server certificate
 * @return a new server certificate and its private key
 */
CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                          X509Certificate caRootCertificate,
                                          PrivateKey caPrivateKey,
                                          KeyPair serverKeyPair,
                                          String messageDigest);
 
Example #24
Source File: SecurityProviderTool.java    From CapturePacket with MIT License 2 votes vote down vote up
/**
 * Creates a new server X.509 certificate using the serverKeyPair. The new certificate will be populated with
 * information from the specified certificateInfo and will be signed using the specified caPrivateKey and messageDigest.
 *
 * @param certificateInfo   basic X.509 certificate info that will be used to create the server certificate
 * @param caRootCertificate root certificate that will be used to populate the issuer field of the server certificate
 * @param serverKeyPair     server's public and private keys
 * @param messageDigest     message digest to use when signing the server certificate, such as SHA512
 * @param caPrivateKey      root certificate private key that will be used to sign the server certificate
 * @return a new server certificate and its private key
 */
CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                          X509Certificate caRootCertificate,
                                          PrivateKey caPrivateKey,
                                          KeyPair serverKeyPair,
                                          String messageDigest);
 
Example #25
Source File: SecurityProviderTool.java    From CapturePacket with MIT License 2 votes vote down vote up
/**
 * Creates a new self-signed CA root certificate, suitable for use signing new server certificates.
 *
 * @param certificateInfo certificate info to populate in the new root cert
 * @param keyPair         root certificate's public and private keys
 * @param messageDigest   digest to use when signing the new root certificate, such as SHA512
 * @return a new root certificate and private key
 */
CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                          KeyPair keyPair,
                                          String messageDigest);
 
Example #26
Source File: SecurityProviderTool.java    From AndroidHttpCapture with MIT License 2 votes vote down vote up
/**
 * Creates a new self-signed CA root certificate, suitable for use signing new server certificates.
 *
 * @param certificateInfo certificate info to populate in the new root cert
 * @param keyPair         root certificate's public and private keys
 * @param messageDigest   digest to use when signing the new root certificate, such as SHA512
 * @return a new root certificate and private key
 */
CertificateAndKey createCARootCertificate(CertificateInfo certificateInfo,
                                          KeyPair keyPair,
                                          String messageDigest);
 
Example #27
Source File: SecurityProviderTool.java    From AndroidHttpCapture with MIT License 2 votes vote down vote up
/**
 * Creates a new server X.509 certificate using the serverKeyPair. The new certificate will be populated with
 * information from the specified certificateInfo and will be signed using the specified caPrivateKey and messageDigest.
 *
 * @param certificateInfo   basic X.509 certificate info that will be used to create the server certificate
 * @param caRootCertificate root certificate that will be used to populate the issuer field of the server certificate
 * @param serverKeyPair     server's public and private keys
 * @param messageDigest     message digest to use when signing the server certificate, such as SHA512
 * @param caPrivateKey      root certificate private key that will be used to sign the server certificate
 * @return a new server certificate and its private key
 */
CertificateAndKey createServerCertificate(CertificateInfo certificateInfo,
                                          X509Certificate caRootCertificate,
                                          PrivateKey caPrivateKey,
                                          KeyPair serverKeyPair,
                                          String messageDigest);