Home > front end >  How to convert Curl SSL requests into Java code
How to convert Curl SSL requests into Java code

Time:02-06

Curl allows making 2-way SSL requests by specifying the certificate and private key files like the two curl requests below

  1. First get an access token:

    $ curl https://connect2.server.com/auth/token
    -H "Authorization: Basic $BASIC_AUTH"
    --cert ~/certs/certpath/fullchain.pem
    --key ~/certs/certpath/privkey.pem

  2. Then use the token to access the API:

    $ curl https://connect2.server.com/api/public/preview1/orgs/$ORGUUID/API
    -H "Authorization: Bearer $ACCESS_TOKEN"
    --cert ~/certs/certpath/fullchain.pem
    --key ~/certs/certpath/privkey.pem

Question:

How to implement the above requests in Java? What libraries are required? Java seems to use p12 file, however, we have .pem files.

CodePudding user response:

‌1. You can convert PEM privatekey plus chain to a PKCS12 file using openssl pkcs12 -export. That is not programming or development and no longer ontopic here, but there are dozens of Qs about this here going back many years when topicality was broader, as well as in other Stacks (security.SX, serverfault, superuser, maybe more).

‌2. If you don't have or dislike OpenSSL, you can read those files (among others) into any kind of Java keystore (JCEKS, JKS, PKCS12, and several BouncyCastle variants you probably don't want) using the software from https://www.keystore-explorer.org . That's also offtopic, and I've seen some existing Qs mention it but not many.

‌3. If you want to do this with your own code, which is ontopic, and assuming your curl uses OpenSSL or at least those files are OpenSSL formats:

3.0 Java can read PEM cert sequence with CertificateFactory.getInstance("X.509") then generateCertificates(InputStream) (note s) -- the doc is a bit sketchy but this method actually can handle separate certs as DER or PEM (which you apparently have), or PKCS7 containing certs as a single blob (commonly called p7b or p7c) ditto.

3.1 if that privkey file is PKCS8-unencrypted, i.e. if the PEM labels are BEGIN/END PRIVATE KEY with no other word between, that case can be handled by standard Java, assuming you know what algorithm it is for (which if necessary you can determine from the first=leaf certificate). Delete the BEGIN/END lines and decode the rest from base64 to binary either ignoring linebreaks (with Base64.getMimeDecoder()) or with .getDecoder() after deleting the linebreaks. Put the result in PKCS8EncodedKeySpec and feed it to generatePrivate in a KeyFactory instance for the correct algorithm.

3.2 BouncyCastle (bcpkix bcprov) can read all the PEM formats for privatekey used by OpenSSL with PEMParser and JcaPEMKeyConverter and if applicable a DecryptorBuilder. There are many existing Qs on this that you can find with that fairly-unique classname. This does mean a dependency on Bouncy.

3.3 if you don't have or don't want Bouncy and have a format other than PKCS8-unencrypted, life gets harder. You could avoid this by using OpenSSL to convert the privkey file to PKCS8-unencrypted putting you back in #3.1, but if you do that you might as well go way back to #1 and use OpenSSL to convert the lot to PKCS12 in one foop.

  • if you have an OpenSSL 'traditional' algorithm-specific format like BEGIN/END RSA PRIVATE KEY or BEGIN/END EC PRIVATE KEY, and the first two lines after BEGIN are NOT Proc-type: 4 and DEK-info, you can base64-decode the body and convert it to PKCS8 by adding a (DER) prefix in front that specifies the algorithm and 'wraps' the algorithm-specific part. I think there are dupes for this but I can't presently find any; if this case applies and you identify the algorithm I'll add it.

  • if you have a 'traditional' format that does have Proc-type: 4 and DEK-info, or you have BEGIN/END ENCRYPTED PRIVATE KEY, those are encrypted. Making sense of them with only standard Java is a fair bit of work which I'll do only if you can't use the other options and specify exactly what case you have.

CodePudding user response:

Following are the steps & code to add SSL certificates into HTTP Post request.

STEP 1. CONVERT PEM CERTIFICATE TO P12 FORMAT

openssl pkcs12 -export -out cacert.p12 -inkey /etc/letsencrypt/archive/server/privkey21.pem -in /etc/letsencrypt/archive/server/cert21.pem -certfile /etc/letsencrypt/archive/server/chain21.pem -passin pass:PWD -passout pass:PWD

STEP 2. (OPTIONAL NOT REQUIRED) CONVERT CERTIFICATE P12 TO JKS FORMAT

keytool -importkeystore -srckeystore cacert.p12 -srcstoretype pkcs12 -destkeystore cacert.jks

STEP 3. ADD CERTIFICATE TO HTTP POST REQUEST THROUGH SSLSocketFactory

/**
* This function is responsible to create createSSLSocketFactory with SSL certificate
* @return
*/
public static SSLSocketFactory createSSLSocketFactory(){
      try 
      {
             FileInputStream f5 = new FileInputStream(new File("/etc/letsencrypt/archive/server/cacert21.p12"));
             KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
             KeyStore ks1 = KeyStore.getInstance(KeyStore.getDefaultType());
             ks1.load(f5, "PWD".toCharArray());
             kmf.init(ks1, "PWD".toCharArray());
             
             SSLContext sslContext = SSLContext.getInstance("SSL");
             sslContext.init(kmf.getKeyManagers(), null, null);
             
             f5.close();
             return sslContext.getSocketFactory();
      }
      catch (Exception e) {
             e.printStackTrace();
             return null;
      }
}
  •  Tags:  
  • Related