Skip to content

Commit 6acb954

Browse files
BAEL-4219 - How to read .pem file to get private and public key (eugenp#9676)
1 parent 51252a0 commit 6acb954

8 files changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.baeldung.pem;
2+
3+
import org.apache.commons.codec.binary.Base64;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.nio.charset.Charset;
8+
import java.nio.file.Files;
9+
import java.security.GeneralSecurityException;
10+
import java.security.KeyFactory;
11+
import java.security.interfaces.RSAPrivateKey;
12+
import java.security.interfaces.RSAPublicKey;
13+
import java.security.spec.PKCS8EncodedKeySpec;
14+
import java.security.spec.X509EncodedKeySpec;
15+
16+
public class JavaSecurityPemUtils {
17+
18+
public static RSAPrivateKey readPKCS8PrivateKey(File file) throws GeneralSecurityException, IOException {
19+
String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
20+
21+
String privateKeyPEM = key
22+
.replace("-----BEGIN PRIVATE KEY-----", "")
23+
.replaceAll(System.lineSeparator(), "")
24+
.replace("-----END PRIVATE KEY-----", "");
25+
26+
byte[] encoded = Base64.decodeBase64(privateKeyPEM);
27+
28+
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
29+
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
30+
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
31+
}
32+
33+
public static RSAPublicKey readX509PublicKey(File file) throws GeneralSecurityException, IOException {
34+
String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
35+
36+
String publicKeyPEM = key
37+
.replace("-----BEGIN PUBLIC KEY-----", "")
38+
.replaceAll(System.lineSeparator(), "")
39+
.replace("-----END PUBLIC KEY-----", "");
40+
41+
byte[] encoded = Base64.decodeBase64(publicKeyPEM);
42+
43+
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
44+
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
45+
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
46+
}
47+
48+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCyO0YiTxLEP44S
3+
IGk/b9MlQAXS6nC4oYyTrAfxHCi/zxW/MmtWbY0K2JxOTkVSD5QbmvwkCutXi0k9
4+
EdDK+orAXg2KSy686O/cfIh/iho6FmNPyEOd7UF+/5wWpknrUaTQyMA2H9Pmr2/E
5+
RH/tN1Q0cqmhFX41WUo3lsRT81DkVCNVeJx+zDGHpjp+XY8gWpPYJ+MP4WQE9TWJ
6+
P2rIlgcDfwhG/A21yK0WAJ5nB0Y+jGI8+HVYdjxXGlRUG//YmxS2sH+sAhsapmjE
7+
Aha+KMk972jVNjdWU7OT0BJnUB5q286Kv6INUnk6kqYufNzjpCAY9SyMjKjpKN71
8+
3Gka2gZBAgMBAAECggEAFlPam12wiik0EQ1CYhIOL3JvyFZaPKbwR2ebrxbJ/A1j
9+
OgqE69TZgGxWWHDxui/9a9/kildb2CG40Q+0SllMnICrzZFRj5TWx5ZKOz//vRsk
10+
4c/CuLwKInC/Cw9V30bhEM61VZJzJ0j/BWVXaU4vHEro+ScKIoDHDWOzwJiQn6m9
11+
C+Ti5lFpax3hx8ZrgPqmBCFYNvErrWkOr7mCYl0jS+E22c68yn8+LjdlF1LWUa6N
12+
zutk3MPj5UwEyR0h7EZReCeGkPTMQNyOBhDcmAtlEno4fjtZzUDHRjh8/QpG1Mz/
13+
alavvrkjswc1DmRUOdgiYu+Waxan5noBhxEAvd/hyQKBgQDjYJD0n+m0tUrpNtX0
14+
+mdzHstClHrpx5oNxs4sIBjCoCwEXaSpeY8+JxCdnZ6n29mLZLq/wPXxZ3EJcOSZ
15+
PYUvZJfV/IUvoLPFbtT3ILzDTcAAeHj2GAOpzYP8J1JSFsc78ZjKMF1XeNjXcq8T
16+
XNXoWfY7N/fShoycVeG42JJCFwKBgQDIqvHL0QfJ8r6yM8Efj7Zq6Wa4C9okORes
17+
8UVWfBoO6UOWvpK+D9IjnaEisJcnEalwNi8/eKudR9hfvmzATV+t3YJIgktto3TT
18+
BWLsEyniNU4vSTl7GPBrV2xabWogbChlt7TXUfw6YogaBKm43snYXBbJFc+NcpQH
19+
ONB5igppZwKBgGDyYHvc3wGsttb/CXTde1RLUfD+a/XXpCixlmCcAtKhBoOKBdY4
20+
vUmL0HrTpLz/cR8NAM8XkAWwzDJxTxbDc1EEu/SCKatoAp5wph8Ed1dyhCXvN+v9
21+
yzoQJXFStrfHfIVjenji7DmKjjI2dM11rMLX8LPJJkI+Gh/iQk7VEG9bAoGAH/aS
22+
sztleTZwR6RUw7k5fkgVM4W3xoNNkR+RQthbsjpXqMBMUXflqgSmsQbd3LxEd/o5
23+
hmurMk9KWN3VJsBsWB5rbS9L4nfh2OcHvcDDsCN7g66vODtduEthl/nLqMRxnton
24+
NRD7EzW0pihN/IOINS1d98PAnrA8gfX7xxBE3ksCgYBvoljHGjvy3bPJ++vDGKJK
25+
y6JuEeRVzgdPXEb60uU+BR7kdh+MMsZLmgfFTgza3R+/xeZcC/cuOPsbzeooRQi/
26+
9NpKwSCXjVNk9nglUWBoPRh4uYqrArWn+HoR7MI/BxeRJm5e1+ii8P19Y9joX5s0
27+
Q3OLn8GeH56ClJmNiWDhsA==
28+
-----END PRIVATE KEY-----
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjtGIk8SxD+OEiBpP2/T
3+
JUAF0upwuKGMk6wH8Rwov88VvzJrVm2NCticTk5FUg+UG5r8JArrV4tJPRHQyvqK
4+
wF4NiksuvOjv3HyIf4oaOhZjT8hDne1Bfv+cFqZJ61Gk0MjANh/T5q9vxER/7TdU
5+
NHKpoRV+NVlKN5bEU/NQ5FQjVXicfswxh6Y6fl2PIFqT2CfjD+FkBPU1iT9qyJYH
6+
A38IRvwNtcitFgCeZwdGPoxiPPh1WHY8VxpUVBv/2JsUtrB/rAIbGqZoxAIWvijJ
7+
Pe9o1TY3VlOzk9ASZ1AeatvOir+iDVJ5OpKmLnzc46QgGPUsjIyo6Sje9dxpGtoG
8+
QQIDAQAB
9+
-----END PUBLIC KEY-----
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.baeldung.pem;
2+
3+
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.io.File;
7+
import java.security.interfaces.RSAPrivateKey;
8+
import java.security.interfaces.RSAPublicKey;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
12+
public class JavaSecurityPemUtilsUnitTest {
13+
14+
@Test
15+
public void whenReadPublicKeyFromPEMFile_thenSuccess() throws Exception {
16+
File pemFile = new File(JavaSecurityPemUtilsUnitTest.class.getResource("/pem/public-key.pem").getFile());
17+
18+
RSAPublicKey publicKey = JavaSecurityPemUtils.readX509PublicKey(pemFile);
19+
20+
assertEquals("X.509", publicKey.getFormat());
21+
assertEquals("RSA", publicKey.getAlgorithm());
22+
}
23+
24+
@Test
25+
public void whenReadPrivateKeyFromPEMFile_thenSuccess() throws Exception {
26+
File pemFile = new File(JavaSecurityPemUtilsUnitTest.class.getResource("/pem/private-key-pkcs8.pem").getFile());
27+
28+
RSAPrivateKey privateKey = JavaSecurityPemUtils.readPKCS8PrivateKey(pemFile);
29+
30+
assertEquals("PKCS#8", privateKey.getFormat());
31+
assertEquals("RSA", privateKey.getAlgorithm());
32+
}
33+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.baeldung.pem;
2+
3+
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
4+
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
5+
import org.bouncycastle.openssl.PEMParser;
6+
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
7+
import org.bouncycastle.util.io.pem.PemObject;
8+
import org.bouncycastle.util.io.pem.PemReader;
9+
10+
import java.io.File;
11+
import java.io.FileReader;
12+
import java.io.IOException;
13+
import java.security.KeyFactory;
14+
import java.security.NoSuchAlgorithmException;
15+
import java.security.interfaces.RSAPrivateKey;
16+
import java.security.interfaces.RSAPublicKey;
17+
import java.security.spec.InvalidKeySpecException;
18+
import java.security.spec.PKCS8EncodedKeySpec;
19+
import java.security.spec.X509EncodedKeySpec;
20+
21+
public class BouncyCastlePemUtils {
22+
23+
public static RSAPublicKey readX509PublicKey(File file) throws InvalidKeySpecException, IOException, NoSuchAlgorithmException {
24+
KeyFactory factory = KeyFactory.getInstance("RSA");
25+
26+
try (FileReader keyReader = new FileReader(file);
27+
PemReader pemReader = new PemReader(keyReader)) {
28+
29+
PemObject pemObject = pemReader.readPemObject();
30+
byte[] content = pemObject.getContent();
31+
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
32+
return (RSAPublicKey) factory.generatePublic(pubKeySpec);
33+
}
34+
}
35+
36+
public static RSAPublicKey readX509PublicKeySecondApproach(File file) throws IOException {
37+
try (FileReader keyReader = new FileReader(file)) {
38+
39+
PEMParser pemParser = new PEMParser(keyReader);
40+
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
41+
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
42+
43+
return (RSAPublicKey) converter.getPublicKey(publicKeyInfo);
44+
}
45+
}
46+
47+
public static RSAPrivateKey readPKCS8PrivateKey(File file) throws InvalidKeySpecException, IOException, NoSuchAlgorithmException {
48+
KeyFactory factory = KeyFactory.getInstance("RSA");
49+
50+
try (FileReader keyReader = new FileReader(file);
51+
PemReader pemReader = new PemReader(keyReader)) {
52+
53+
PemObject pemObject = pemReader.readPemObject();
54+
byte[] content = pemObject.getContent();
55+
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
56+
return (RSAPrivateKey) factory.generatePrivate(privKeySpec);
57+
}
58+
}
59+
60+
public static RSAPrivateKey readPKCS8PrivateKeySecondApproach(File file) throws IOException {
61+
try (FileReader keyReader = new FileReader(file)) {
62+
63+
PEMParser pemParser = new PEMParser(keyReader);
64+
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
65+
PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance(pemParser.readObject());
66+
67+
return (RSAPrivateKey) converter.getPrivateKey(privateKeyInfo);
68+
}
69+
}
70+
71+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCyO0YiTxLEP44S
3+
IGk/b9MlQAXS6nC4oYyTrAfxHCi/zxW/MmtWbY0K2JxOTkVSD5QbmvwkCutXi0k9
4+
EdDK+orAXg2KSy686O/cfIh/iho6FmNPyEOd7UF+/5wWpknrUaTQyMA2H9Pmr2/E
5+
RH/tN1Q0cqmhFX41WUo3lsRT81DkVCNVeJx+zDGHpjp+XY8gWpPYJ+MP4WQE9TWJ
6+
P2rIlgcDfwhG/A21yK0WAJ5nB0Y+jGI8+HVYdjxXGlRUG//YmxS2sH+sAhsapmjE
7+
Aha+KMk972jVNjdWU7OT0BJnUB5q286Kv6INUnk6kqYufNzjpCAY9SyMjKjpKN71
8+
3Gka2gZBAgMBAAECggEAFlPam12wiik0EQ1CYhIOL3JvyFZaPKbwR2ebrxbJ/A1j
9+
OgqE69TZgGxWWHDxui/9a9/kildb2CG40Q+0SllMnICrzZFRj5TWx5ZKOz//vRsk
10+
4c/CuLwKInC/Cw9V30bhEM61VZJzJ0j/BWVXaU4vHEro+ScKIoDHDWOzwJiQn6m9
11+
C+Ti5lFpax3hx8ZrgPqmBCFYNvErrWkOr7mCYl0jS+E22c68yn8+LjdlF1LWUa6N
12+
zutk3MPj5UwEyR0h7EZReCeGkPTMQNyOBhDcmAtlEno4fjtZzUDHRjh8/QpG1Mz/
13+
alavvrkjswc1DmRUOdgiYu+Waxan5noBhxEAvd/hyQKBgQDjYJD0n+m0tUrpNtX0
14+
+mdzHstClHrpx5oNxs4sIBjCoCwEXaSpeY8+JxCdnZ6n29mLZLq/wPXxZ3EJcOSZ
15+
PYUvZJfV/IUvoLPFbtT3ILzDTcAAeHj2GAOpzYP8J1JSFsc78ZjKMF1XeNjXcq8T
16+
XNXoWfY7N/fShoycVeG42JJCFwKBgQDIqvHL0QfJ8r6yM8Efj7Zq6Wa4C9okORes
17+
8UVWfBoO6UOWvpK+D9IjnaEisJcnEalwNi8/eKudR9hfvmzATV+t3YJIgktto3TT
18+
BWLsEyniNU4vSTl7GPBrV2xabWogbChlt7TXUfw6YogaBKm43snYXBbJFc+NcpQH
19+
ONB5igppZwKBgGDyYHvc3wGsttb/CXTde1RLUfD+a/XXpCixlmCcAtKhBoOKBdY4
20+
vUmL0HrTpLz/cR8NAM8XkAWwzDJxTxbDc1EEu/SCKatoAp5wph8Ed1dyhCXvN+v9
21+
yzoQJXFStrfHfIVjenji7DmKjjI2dM11rMLX8LPJJkI+Gh/iQk7VEG9bAoGAH/aS
22+
sztleTZwR6RUw7k5fkgVM4W3xoNNkR+RQthbsjpXqMBMUXflqgSmsQbd3LxEd/o5
23+
hmurMk9KWN3VJsBsWB5rbS9L4nfh2OcHvcDDsCN7g66vODtduEthl/nLqMRxnton
24+
NRD7EzW0pihN/IOINS1d98PAnrA8gfX7xxBE3ksCgYBvoljHGjvy3bPJ++vDGKJK
25+
y6JuEeRVzgdPXEb60uU+BR7kdh+MMsZLmgfFTgza3R+/xeZcC/cuOPsbzeooRQi/
26+
9NpKwSCXjVNk9nglUWBoPRh4uYqrArWn+HoR7MI/BxeRJm5e1+ii8P19Y9joX5s0
27+
Q3OLn8GeH56ClJmNiWDhsA==
28+
-----END PRIVATE KEY-----
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjtGIk8SxD+OEiBpP2/T
3+
JUAF0upwuKGMk6wH8Rwov88VvzJrVm2NCticTk5FUg+UG5r8JArrV4tJPRHQyvqK
4+
wF4NiksuvOjv3HyIf4oaOhZjT8hDne1Bfv+cFqZJ61Gk0MjANh/T5q9vxER/7TdU
5+
NHKpoRV+NVlKN5bEU/NQ5FQjVXicfswxh6Y6fl2PIFqT2CfjD+FkBPU1iT9qyJYH
6+
A38IRvwNtcitFgCeZwdGPoxiPPh1WHY8VxpUVBv/2JsUtrB/rAIbGqZoxAIWvijJ
7+
Pe9o1TY3VlOzk9ASZ1AeatvOir+iDVJ5OpKmLnzc46QgGPUsjIyo6Sje9dxpGtoG
8+
QQIDAQAB
9+
-----END PUBLIC KEY-----
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.baeldung.pem;
2+
3+
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.io.File;
7+
import java.security.interfaces.RSAPrivateKey;
8+
import java.security.interfaces.RSAPublicKey;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
12+
public class BouncyCastlePemUtilsUnitTest {
13+
14+
@Test
15+
public void whenReadPublicKeyFromPEMFile_thenSuccess() throws Exception {
16+
File pemFile = new File(BouncyCastlePemUtilsUnitTest.class.getResource("/pem/public-key.pem").getFile());
17+
18+
RSAPublicKey publicKey1 = BouncyCastlePemUtils.readX509PublicKey(pemFile);
19+
RSAPublicKey publicKey2 = BouncyCastlePemUtils.readX509PublicKeySecondApproach(pemFile);
20+
21+
assertEquals("X.509", publicKey1.getFormat());
22+
assertEquals("RSA", publicKey1.getAlgorithm());
23+
24+
assertEquals("X.509", publicKey2.getFormat());
25+
assertEquals("RSA", publicKey2.getAlgorithm());
26+
}
27+
28+
@Test
29+
public void whenReadPrivateKeyFromPEMFile_thenSuccess() throws Exception {
30+
File pemFile = new File(BouncyCastlePemUtilsUnitTest.class.getResource("/pem/private-key-pkcs8.pem").getFile());
31+
32+
RSAPrivateKey privateKey1 = BouncyCastlePemUtils.readPKCS8PrivateKey(pemFile);
33+
RSAPrivateKey privateKey2 = BouncyCastlePemUtils.readPKCS8PrivateKeySecondApproach(pemFile);
34+
35+
assertEquals("PKCS#8", privateKey1.getFormat());
36+
assertEquals("RSA", privateKey1.getAlgorithm());
37+
38+
assertEquals("PKCS#8", privateKey2.getFormat());
39+
assertEquals("RSA", privateKey2.getAlgorithm());
40+
}
41+
}

0 commit comments

Comments
 (0)