Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have pem certificate with private key and server certificate. I can execute it using curl and all works ok.

curl -O -k --cert-type pem --cert mypem.pem url

But I want to use it with java, most preferably will be RestTemplate from spring.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
498 views
Welcome To Ask or Share your Answers For Others

1 Answer

So knowledge about using pem certificate with RestTemplate is distracted.

Steps which must be done:

  1. Add server certificate to trustStore, using keytool or portecle. When you want to use custom trusttore use this script

  2. Next configure ssl to RestTemplate. It may be done like below:

    @Configuration
    public class SSLConfiguration {
    
    @Value("${certificate.name}")
    private String name;
    
    @Bean(name = "sslContext")
    public SSLContext sslContext() throws Exception {
      Security.addProvider(new BouncyCastleProvider());
      return SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build();
    }
    
    @Bean(name = "sslSocketFactory")
    public SSLSocketFactory sslSocketFactory() throws Exception {
    
      return new ConnectionFactoryCreator(name, sslContext()).getSocketFactory();
    
    }
    
    @Bean(name = "httpClient")
    public HttpClient httpClient() throws Exception {
      return HttpClientBuilder.create().setSslcontext(sslContext())
            .setSSLSocketFactory(new SSLConnectionSocketFactory(sslSocketFactory(), new AllowAllHostnameVerifier()))
            .build();
    }
    
    @Bean
    public ClientHttpRequestFactory httpClientRequestFactory() throws Exception {
      return new HttpComponentsClientHttpRequestFactory(httpClient());
    }
    
    @Bean
    public RestTemplate restTemplate() throws Exception {
      return new RestTemplate(httpClientRequestFactory());
     }
    
    }
    

and

public class ConnectionFactoryCreator {

   private final String pemName;

   private final SSLContext context;

   public ConnectionFactoryCreator(String pemName, SSLContext context) {
      this.pemName = pemName;
      this.context = context;
   }

   public SSLSocketFactory getSocketFactory() throws Exception {

      InputStream resourceAsStream = getClass().getResourceAsStream(pemName);
  byte[] certAndKey = ByteStreams.toByteArray(resourceAsStream);

  byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
  byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");

  X509Certificate cert = generateCertificateFromDER(certBytes);

  PrivateKey key = generatePrivateKeyFromDER(keyBytes);

  KeyStore keystore = KeyStore.getInstance("JKS");
  keystore.load(null);
  keystore.setCertificateEntry("cert-alias", cert);
  keystore.setKeyEntry("key-alias", key, "changeit".toCharArray(), new Certificate[] { cert });

  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(keystore, "changeit".toCharArray());

  KeyManager[] km = kmf.getKeyManagers();

  context.init(km, null, null);

  return context.getSocketFactory();
   }

   private byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
  String data = new String(pem);
  String[] tokens = data.split(beginDelimiter);
  tokens = tokens[1].split(endDelimiter);
  return DatatypeConverter.parseBase64Binary(tokens[0]);
   }

   private PrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
     throws InvalidKeySpecException, NoSuchAlgorithmException {
  PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

  KeyFactory factory = KeyFactory.getInstance("RSA");

  return factory.generatePrivate(spec);
   }

   private X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
  CertificateFactory factory = CertificateFactory.getInstance("X.509");

  return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
 }

Finally you can use inject restTemplate to connect to url.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...