How to Configure TLS/SSL With PEM Files
This tutorial will explain to you how to easily configure your favorite http client for java, kotlin, and scala with tls/ssl while using PEM files instead of the traditional jks or p12 files. I will use the traditional http client of the jdk, HttpURLConnection, as an example for this tutorial. But you can find here 30+ other client examples: Example HTTP Client configurations.
We will send an https request to https://client.badssl.com/ where the client needs to authenticate itself with its own certificates. This is also known as mutual authentication. The server will require the client to identify itself and both parties need to trust each other. Without identification, you will receive a 400 Bad Request as a response. If it passes you will receive a status code 200.
The client identity as badssl-identity.pem:
Bag Attributes
localKeyID: 41 C3 6C 33 C7 E3 36 DD EA 4A 1F C0 B7 23 B8 E6 9C DC D8 0F
subject=C = US, ST = California, L = San Francisco, O = BadSSL, CN = BadSSL Client Certificate
issuer=C = US, ST = California, L = San Francisco, O = BadSSL, CN = BadSSL Client Root Certificate Authority
-----BEGIN CERTIFICATE-----
MIIEqDCCApCgAwIBAgIUK5Ns4y2CzosB/ZoFlaxjZqoBTIIwDQYJKoZIhvcNAQEL
BQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDExMC8GA1UEAwwoQmFkU1NM
IENsaWVudCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xOTExMjcwMDE5
NTdaFw0yMTExMjYwMDE5NTdaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wx
IjAgBgNVBAMMGUJhZFNTTCBDbGllbnQgQ2VydGlmaWNhdGUwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDHN18R6x5Oz+u6SOXLoxIscz5GHR6cDcCLgyPa
x2XfXHdJs+h6fTy61WGM+aXEhR2SIwbj5997s34m0MsbvkJrFmn0LHK1fuTLCihE
EmxGdCGZA9xrwxFYAkEjP7D8v7cAWRMipYF/JP7VU7xNUo+QSkZ0sOi9k6bNkABK
L3+yP6PqAzsBoKIN5lN/YRLrppsDmk6nrRDo4R3CD+8JQl9quEoOmL22Pc/qpOjL
1jgOIFSE5y3gwbzDlfCYoAL5V+by1vu0yJShTTK8oo5wvphcFfEHaQ9w5jFg2htd
q99UER3BKuNDuL+zejqGQZCWb0Xsk8S5WBuX8l3Brrg5giqNAgMBAAGjLTArMAkG
A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgeAMAsGA1UdDwQEAwIF4DANBgkqhkiG
9w0BAQsFAAOCAgEAZBauLzFSOijkDadcippr9C6laHebb0oRS54xAV70E9k5GxfR
/E2EMuQ8X+miRUMXxKquffcDsSxzo2ac0flw94hDx3B6vJIYvsQx9Lzo95Im0DdT
DkHFXhTlv2kjQwFVnEsWYwyGpHMTjanvNkO7sBP9p1bN1qTE3QAeyMZNKWJk5xPl
U298ERar6tl3Z2Cl8mO6yLhrq4ba6iPGw08SENxzuAJW+n8r0rq7EU+bMg5spgT1
CxExzG8Bb0f98ZXMklpYFogkcuH4OUOFyRodotrotm3iRbuvZNk0Zz7N5n1oLTPl
bGPMwBcqaGXvK62NlaRkwjnbkPM4MYvREM0bbAgZD2GHyANBTso8bdWvhLvmoSjs
FSqJUJp17AZ0x/ELWZd69v2zKW9UdPmw0evyVR19elh/7dmtF6wbewc4N4jxQnTq
IItuhIWKWB9edgJz65uZ9ubQWjXoa+9CuWcV/1KxuKCbLHdZXiboLrKm4S1WmMYW
d0sJm95H9mJzcLyhLF7iX2kK6K9ug1y02YCVXBC9WGZc2x6GMS7lDkXSkJFy3EWh
CmfxkmFGwOgwKt3Jd1pF9ftcSEMhu4WcMgxi9vZr9OdkJLxmk033sVKI/hnkPaHw
g0Y2YBH5v0xmi8sYU7weOcwynkjZARpUltBUQ0pWCF5uJsEB8uE8PPDD3c4=
-----END CERTIFICATE-----
Bag Attributes
localKeyID: 41 C3 6C 33 C7 E3 36 DD EA 4A 1F C0 B7 23 B8 E6 9C DC D8 0F
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIy3Fposf+2ccCAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECFOXAIo35o51BIIEyLsnLgbzRpsI
qsephRcXVWt4lXgWF1uHD+mFL9JMqC8K1ESV/SUbIAaINziWlyBjkkCduPMOHbER
6zUP60ixisPi8jkihkV1bvJvWeHXsQjjTAYXtwVX2s9T5D+IYK4CF8lOe5eiG1Pb
UV3oD78zcOeM+aGRjSDKneSx4bUFiv33bziBDAtnk6Ts5lg6x5HtM0YQBCycqpMH
I7jpafH+TZSVqdyAdL8Jc5bByAQk8SWvEFXxPP5RS9YfeOd3WDvzJQaHSw8otf6h
lpimxbXhOrI84r1YZwDy/3QaYdnKUPBYSZniBje2G/g0Su5ZanCvvhhhhQlN18QO
AjQGEZKlfuxi8cq/EZWqFrnui6KSiutCmcnMyJ8mcS2dDGVsr3GVPpnyzpokSTY1
q2o/b9hqV/9ETzVYeNyO4L5MVIuxTxM8hNj4gkmFMkv8diDS6TmKO2kOasZAuUYO
Eq+diZKj1CZg+qejf3u+93fycyk9b1rrsL6iG24QMdHgTsn/ZyX85ZUHFXba+qWn
G2rZsseBR4UcKxjUWO7ElH6oD8WUP/St7/88q5XFV1AuC0CGc6L+a4je3EbKjhK8
9fFXgSXbYMPIOQ1y0ShHt3YNpRKOCoV2mwZE1FtVIGGlUlu30kY/Ov93sXGYUvtm
/b+GMQrc7tZq7l5qNoI253zfhgX2gWOmU092JAPoDvzDz0QP2vVjB4BqlNJKuOBP
IKBckCQbj4mKWy27LVCMZfylU08k5KfUyvEHxwmD5aj+LClZzGS1GkeQcG80RYrl
DGeLkQXC+li/cSxmKhQ2RPfZ4xR1ImzQdFQJsm9dcHq5arwU5W/N2t3c/0mORKIp
j5mJCm8IVlVP05Rnxmz2wtL+VnUt7M9BQjeUDs155X4Rqp8j24bCtonp8fCnejjw
fBu83zTjo+a8eHTWsyjfJyDnTSNq1HgyWDGhkTSWLW7+UVrG8bUuuGI+C0HtRuPp
49XHrcHXBSufM+t8YHf+DebZ/7dJNnL1DqVOGaFh5fyYJNtMAd1IyT9NkCOq6d22
p1bXFQF5IWrrNJ1FMRT6GzkAUYHd86jGJUuNm1vPqAAF/8eoow2PK75Qu8G+hIjY
k03mUAZzQn12tHidMAVS08frmYBMwmIEwWK+AlOGA8jJoyfJ06dRDN8qcIQ3RQSP
uH/chBsmO/0HPKQYE19fAqqxLQqzaU1yqq6UStTyDCvsuZdJnAwQEi43Wzt3EkNk
50i5fZp6me1x80LARRZFDv5YjEb+hbK4BjKPAoRHL1BbYM5uhGV2F08Y6qqVBhK0
uG1ykwxhnNkS49/7dVwoayBKHHvCbeoOw+E3qmvKfc3jpI93osYGCzFPP0+dKpZN
szfrkI35gVnPSdh0SCSBMLcqkeFMyAeKH4fL13KckU0swe2WSYk/JZlay5Ba+HRM
5zd/j0SAGYYOjvBMrhbLU5g9q2llanv7i8zEHKcb3LzeEaD7XoK5OEHnth9c5Lyx
HD2IxzftLN5J1pXHvioi+KTNJNS4z2k35AQCyNez+g8gFmuhsssYD9dUjEjhbNra
C+D/XlHAZDESksribfm4nTuOOQiyVzdKJ8Xmxsy9Ckjcq5gn5jNvsv96eP2QC5ok
FHeRMpMdlCLXw78iQ6HjJw==
-----END ENCRYPTED PRIVATE KEY-----
And the trusted certificates as badssl-certificate.pem:
xxxxxxxxxx
-----BEGIN CERTIFICATE-----
MIIGqDCCBZCgAwIBAgIQCvBs2jemC2QTQvCh6x1Z/TANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMjAwMzIzMDAwMDAwWhcN
MjIwNTE3MTIwMDAwWjBuMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5p
YTEVMBMGA1UEBxMMV2FsbnV0IENyZWVrMRwwGgYDVQQKExNMdWNhcyBHYXJyb24g
VG9ycmVzMRUwEwYDVQQDDAwqLmJhZHNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDCBOz4jO4EwrPYUNVwWMyTGOtcqGhJsCK1+ZWesSssdj5s
wEtgTEzqsrTAD4C2sPlyyYYC+VxBXRMrf3HES7zplC5QN6ZnHGGM9kFCxUbTFocn
n3TrCp0RUiYhc2yETHlV5NFr6AY9SBVSrbMo26r/bv9glUp3aznxJNExtt1NwMT8
U7ltQq21fP6u9RXSM0jnInHHwhR6bCjqN0rf6my1crR+WqIW3GmxV0TbChKr3sMP
R3RcQSLhmvkbk+atIgYpLrG6SRwMJ56j+4v3QHIArJII2YxXhFOBBcvm/mtUmEAn
hccQu3Nw72kYQQdFVXz5ZD89LMOpfOuTGkyG0cqFAgMBAAGjggNhMIIDXTAfBgNV
HSMEGDAWgBQPgGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUne7Be4ELOkdp
cRh9ETeTvKUbP/swIwYDVR0RBBwwGoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29t
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
awYDVR0fBGQwYjAvoC2gK4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Et
c2hhMi1nNi5jcmwwL6AtoCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2Nh
LXNoYTItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUH
AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIDMHwGCCsG
AQUFBwEBBHAwbjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
MEYGCCsGAQUFBzAChjpodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
cnRTSEEyU2VjdXJlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwggF+BgorBgEE
AdZ5AgQCBIIBbgSCAWoBaAB2ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaO
HtGFAAABcQhGXioAAAQDAEcwRQIgDfWVBXEuUZC2YP4Si3AQDidHC4U9e5XTGyG7
SFNDlRkCIQCzikrA1nf7boAdhvaGu2Vkct3VaI+0y8p3gmonU5d9DwB2ACJFRQdZ
VSRWlj+hL/H3bYbgIyZjrcBLf13Gg1xu4g8CAAABcQhGXlsAAAQDAEcwRQIhAMWi
Vsi2vYdxRCRsu/DMmCyhY0iJPKHE2c6ejPycIbgqAiAs3kSSS0NiUFiHBw7QaQ/s
GO+/lNYvjExlzVUWJbgNLwB2AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7U
iwXlAAABcQhGXnoAAAQDAEcwRQIgKsntiBqt8Au8DAABFkxISELhP3U/wb5lb76p
vfenWL0CIQDr2kLhCWP/QUNxXqGmvr1GaG9EuokTOLEnGPhGv1cMkDANBgkqhkiG
9w0BAQsFAAOCAQEA0RGxlwy3Tl0lhrUAn2mIi8LcZ9nBUyfAcCXCtYyCdEbjIP64
xgX6pzTt0WJoxzlT+MiK6fc0hECZXqpkTNVTARYtGkJoljlTK2vAdHZ0SOpm9OT4
RLfjGnImY0hiFbZ/LtsvS2Zg7cVJecqnrZe/za/nbDdljnnrll7C8O5naQuKr4te
uice3e8a4TtviFwS/wdDnJ3RrE83b1IljILbU5SV0X1NajyYkUWS7AnOmrFUUByz
MwdGrM6kt0lfJy/gvGVsgIKZocHdedPeECqAtq7FAJYanOsjNN9RbBOGhbwq0/FP
CC01zojqS10nGowxzOiqyB4m6wytmzf0QwjpMw==
-----END CERTIFICATE-----
The following code snippet will use these two files and generate the required objects and with that, you can execute an https request with those ssl materials. See below for the example usage:
x
var keyManager = PemUtils.loadIdentityMaterial("badssl-identity.pem", "badssl.com".toCharArray());
var trustManager = PemUtils.loadTrustMaterial("badssl-certificate.pem");
SSLFactory sslFactory = SSLFactory.builder()
.withIdentityMaterial(keyManager)
.withTrustMaterial(trustManager)
.build();
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://client.badssl.com/").openConnection();
connection.setSSLSocketFactory(sslFactory.getSslSocketFactory());
connection.setHostnameVerifier(sslFactory.getHostnameVerifier());
connection.setRequestMethod("GET");
int statusCode = connection.getResponseCode();
System.out.println(statusCode);
The above code snippet is available here: SSLFactoryIT
See here for all other use cases: GitHub - SSLContext Kickstart
And find here an example for other http clients: Example HTTP Client configurations