Java Key Store에 PEM Import
인증이 필요한 SSL 서버에 접속하려고 합니다.Apache MINA에서 SSL을 사용하려면 적절한 JKS 파일이 필요합니다.단, 받은 것은 " "뿐입니다.PEM 파일
PEM 파일에서 JKS 파일을 작성하려면 어떻게 해야 합니까?
먼저 증명서를 DER 형식으로 변환합니다.
openssl x509 -outform der -in certificate.pem -out certificate.der
그런 다음 키스토어에 Import합니다.
keytool -import -alias your-alias -keystore cacerts -file certificate.der
PEM 형식의 증명서만 키스토어에 Import하는 경우 keytool은 다음 작업을 수행합니다.
keytool -import -alias *alias* -keystore cacerts -file *cert.pem*
PEM 증명서를 Java 키스토어에 직접 Import하는 http://code.google.com/p/java-keyutil/을 개발했습니다.주요 목적은 ca-bundle.crt 등의 여러 부분으로 구성된 PEM 운영체제 증명서 번들을 Import하는 것입니다.여기에는 종종 키툴이 처리할 수 없는 헤더가 포함됩니다.
</self promotion>
외부 도구(opensl, keytool)를 사용하지 않고 Java에서 PEM 파일을 쉽게 로드할 수 있는 방법이 필요한 경우 프로덕션에서 사용하는 코드를 다음과 같습니다.
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import javax.xml.bind.DatatypeConverter;
public class PEMImporter {
public static SSLServerSocketFactory createSSLFactory(File privateKeyPem, File certificatePem, String password) throws Exception {
final SSLContext context = SSLContext.getInstance("TLS");
final KeyStore keystore = createKeyStore(privateKeyPem, certificatePem, password);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, password.toCharArray());
final KeyManager[] km = kmf.getKeyManagers();
context.init(km, null, null);
return context.getServerSocketFactory();
}
/**
* Create a KeyStore from standard PEM files
*
* @param privateKeyPem the private key PEM file
* @param certificatePem the certificate(s) PEM file
* @param the password to set to protect the private key
*/
public static KeyStore createKeyStore(File privateKeyPem, File certificatePem, final String password)
throws Exception, KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
final X509Certificate[] cert = createCertificates(certificatePem);
final KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
// Import private key
final PrivateKey key = createPrivateKey(privateKeyPem);
keystore.setKeyEntry(privateKeyPem.getName(), key, password.toCharArray(), cert);
return keystore;
}
private static PrivateKey createPrivateKey(File privateKeyPem) throws Exception {
final BufferedReader r = new BufferedReader(new FileReader(privateKeyPem));
String s = r.readLine();
if (s == null || !s.contains("BEGIN PRIVATE KEY")) {
r.close();
throw new IllegalArgumentException("No PRIVATE KEY found");
}
final StringBuilder b = new StringBuilder();
s = "";
while (s != null) {
if (s.contains("END PRIVATE KEY")) {
break;
}
b.append(s);
s = r.readLine();
}
r.close();
final String hexString = b.toString();
final byte[] bytes = DatatypeConverter.parseBase64Binary(hexString);
return generatePrivateKeyFromDER(bytes);
}
private static X509Certificate[] createCertificates(File certificatePem) throws Exception {
final List<X509Certificate> result = new ArrayList<X509Certificate>();
final BufferedReader r = new BufferedReader(new FileReader(certificatePem));
String s = r.readLine();
if (s == null || !s.contains("BEGIN CERTIFICATE")) {
r.close();
throw new IllegalArgumentException("No CERTIFICATE found");
}
StringBuilder b = new StringBuilder();
while (s != null) {
if (s.contains("END CERTIFICATE")) {
String hexString = b.toString();
final byte[] bytes = DatatypeConverter.parseBase64Binary(hexString);
X509Certificate cert = generateCertificateFromDER(bytes);
result.add(cert);
b = new StringBuilder();
} else {
if (!s.startsWith("----")) {
b.append(s);
}
}
s = r.readLine();
}
r.close();
return result.toArray(new X509Certificate[result.size()]);
}
private static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
final KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) factory.generatePrivate(spec);
}
private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
final CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
}
즐겁게 보내세요.
제 경우, 상호 SSL 인증에 사용되는 2개의 증명서와 암호화된 개인 키가 포함된 pem 파일이 있었습니다.제 pem 파일은 다음과 같습니다.
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,C8BF220FC76AA5F9
...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
내가 한 일은 이렇다.
파일을 3개의 개별 파일로 분할하여 각 파일에 1개의 엔트리가 포함되도록 합니다.---BEGIN..으로 끝나다---END..3개의 파일이 있다고 가정해 봅시다.cert1.pem,cert2.pem,그리고.pkey.pem.
변환pkey.pemopenssl 및 다음 구문을 사용하여 DER 형식으로 변환합니다.
openssl pkcs8 - topk8 - nocrypt - in pkey.pem - inform PEM - out pkey.der - outform DER
개인 키가 암호화되어 있는 경우는 패스워드(원래 pem 파일 공급자로부터 취득)를 입력해, DER 포맷으로 변환할 필요가 있습니다.openssl다음과 같이 비밀번호를 입력하도록 요구됩니다.pkey.pem: ".
변환에 성공하면 라는 새 파일을 받게 됩니다.pkey.der.
새 Java 키스토어를 생성하여 개인 키와 증명서를 Import합니다.
String keypass = "password"; // this is a new password, you need to come up with to protect your java key store file
String defaultalias = "importkey";
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
// this section does not make much sense to me,
// but I will leave it intact as this is how it was in the original example I found on internet:
ks.load( null, keypass.toCharArray());
ks.store( new FileOutputStream ( "mykeystore" ), keypass.toCharArray());
ks.load( new FileInputStream ( "mykeystore" ), keypass.toCharArray());
// end of section..
// read the key file from disk and create a PrivateKey
FileInputStream fis = new FileInputStream("pkey.der");
DataInputStream dis = new DataInputStream(fis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
byte[] key = new byte[bais.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
bais.read(key, 0, bais.available());
bais.close();
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
PrivateKey ff = kf.generatePrivate (keysp);
// read the certificates from the files and load them into the key store:
Collection col_crt1 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert1.pem"));
Collection col_crt2 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert2.pem"));
Certificate crt1 = (Certificate) col_crt1.iterator().next();
Certificate crt2 = (Certificate) col_crt2.iterator().next();
Certificate[] chain = new Certificate[] { crt1, crt2 };
String alias1 = ((X509Certificate) crt1).getSubjectX500Principal().getName();
String alias2 = ((X509Certificate) crt2).getSubjectX500Principal().getName();
ks.setCertificateEntry(alias1, crt1);
ks.setCertificateEntry(alias2, crt2);
// store the private key
ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), chain );
// save the key store to a file
ks.store(new FileOutputStream ( "mykeystore" ),keypass.toCharArray());
(임의) 새로운 키스토어의 내용을 확인합니다.
$ keytool -list -keystore mykeystore -storepass password
Keystore 유형: JKS Keystore 공급자: SUN
키 스토어에는 3개의 엔트리가 있습니다.
cn=...,ou=...,o=..,2014년 9월 2일, trustedCertEntry,인증서 지문(SHA1):2C:B8:...
importkey, 2014년 9월 2일, PrivateKeyEntry, 증명서 지문(SHA1) : 9C : B0 : ...
cn=....,o=...., 2014년 9월 2일, trustedCertEntry, 인증서 지문(SHA1): 83:63:...
(옵션)새 키 저장소의 인증서와 개인 키를 SSL 서버에 대해 테스트합니다(VM 옵션으로 디버깅을 사용하도록 설정할 수 있습니다. -Djavax.net.debug=all )
char[] passw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load(new FileInputStream ( "mykeystore" ), passw );
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passw);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
SSLContext sclx = SSLContext.getInstance("TLS");
sclx.init( kmf.getKeyManagers(), tm, null);
SSLSocketFactory factory = sclx.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket( "192.168.1.111", 443 );
socket.startHandshake();
//if no exceptions are thrown in the startHandshake method, then everything is fine..
마지막으로 증명서를 Https에 등록합니다.URL 사용할 계획인 경우 연결:
char[] passw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load(new FileInputStream ( "mykeystore" ), passw );
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passw);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
SSLContext sclx = SSLContext.getInstance("TLS");
sclx.init( kmf.getKeyManagers(), tm, null);
HostnameVerifier hv = new HostnameVerifier()
{
public boolean verify(String urlHostName, SSLSession session)
{
if (!urlHostName.equalsIgnoreCase(session.getPeerHost()))
{
System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultSSLSocketFactory( sclx.getSocketFactory() );
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Keystore Explorer 사용
- 개인 키로 JKS 열기
- CA에서 서명된 PEM을 조사합니다.
- Import 키
- JKS 저장
가끔 하는 일이기 때문에 항상 이 방법을 잊어버리고 있습니다.이 방법은 가능한 해결책 중 하나입니다.그냥 효과가 있습니다.
- 즐겨찾기 브라우저로 이동하여 보안 보호된 웹 사이트에서 기본 인증서를 다운로드합니다.
다음 두 줄의 코드를 실행합니다.
$ openssl x509 -outform der -in GlobalSignRootCA.crt -out GlobalSignRootCA.der $ keytool -import -alias GlobalSignRootCA -keystore GlobalSignRootCA.jks -file GlobalSignRootCA.derJava SE 환경에서 실행하는 경우 다음 옵션을 추가합니다.
$ java -Djavax.net.ssl.trustStore=GlobalSignRootCA.jks -Djavax.net.ssl.trustStorePassword=trustStorePassword -jar MyJar.jar또는 Java 코드에 다음 항목을 추가합니다.
System.setProperty("javax.net.ssl.trustStore", "GlobalSignRootCA.jks"); System.setProperty("javax.net.ssl.trustStorePassword","trustStorePassword");
는 2단계는 그냥 2단계, 2단계는 2단계, 2단계는 2단계만 하시면 됩니다.keytool명령어를 입력합니다.Bellow(Bellow)
$ keytool -import -file org.eu.crt -alias orgcrt -keystore globalsignrs.jks
$ keytool -import -file GlobalSignOrganizationValidationCA-SHA256-G2.crt -alias globalsignorgvalca -keystore globalsignrs.jks
$ keytool -import -file GlobalSignRootCA.crt -alias globalsignrootca -keystore globalsignrs.jks
비주얼 JKS 작성과 증명서 Import를 가능하게 하는 GUI 툴도 있습니다.
http://portecle.sourceforge.net/
Portecle은 키스토어, 키, 증명서, 증명서 요구, 증명서 취소 목록 등을 작성, 관리 및 검사하기 위한 사용자 친화적인 GUI 어플리케이션입니다.
인터넷에서 구했어요.여러 엔트리가 포함된 pem 파일에 매우 적합합니다.
#!/bin/bash
pemToJks()
{
# number of certs in the PEM file
pemCerts=$1
certPass=$2
newCert=$(basename "$pemCerts")
newCert="${newCert%%.*}"
newCert="${newCert}"".JKS"
##echo $newCert $pemCerts $certPass
CERTS=$(grep 'END CERTIFICATE' $pemCerts| wc -l)
echo $CERTS
# For every cert in the PEM file, extract it and import into the JKS keystore
# awk command: step 1, if line is in the desired cert, print the line
# step 2, increment counter when last line of cert is found
for N in $(seq 0 $(($CERTS - 1))); do
ALIAS="${pemCerts%.*}-$N"
cat $pemCerts |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" |
$KEYTOOLCMD -noprompt -import -trustcacerts \
-alias $ALIAS -keystore $newCert -storepass $certPass
done
}
pemToJks <pem to import> <pass for new jks>
비록 이 질문은 꽤 오래되었고 이미 a-lot의 답을 가지고 있지만, 나는 대안을 제시할 가치가 있다고 생각한다.네이티브 Java 클래스를 사용하면 pem 파일만 사용하는 것이 매우 상세하고 pem 파일을 p12 또는 jks 파일로 변환하는 것이 훨씬 쉬워지기 때문에 pem 파일을 p12 또는 jks 파일로 변환하는 것은 거의 강제적입니다.저는 이미 제공된 답변에 대한 대안을 원하는 모든 사람에게 드리고 싶습니다.
var keyManager = PemUtils.loadIdentityMaterial("certificate-chain.pem", "private-key.pem");
var trustManager = PemUtils.loadTrustMaterial("some-trusted-certificate.pem");
var sslFactory = SSLFactory.builder()
.withIdentityMaterial(keyManager)
.withTrustMaterial(trustManager)
.build();
var sslContext = sslFactory.getSslContext();
여기에 몇 가지 면책사항을 제시해야 합니다. 저는 도서관 관리자입니다.
언급URL : https://stackoverflow.com/questions/2138940/import-pem-into-java-key-store
'source' 카테고리의 다른 글
| 구조 할당 또는 memcpy? (0) | 2022.07.23 |
|---|---|
| 컴파일러에서 8비트로 표시되는 부울 값.운영이 비효율적인가요? (0) | 2022.07.23 |
| VueJ - 빌드 후 여러 js 파일이 dist에 있음 (0) | 2022.07.23 |
| null Boolean이 true인지 여부를 확인합니다. 결과는 예외입니다. (0) | 2022.07.23 |
| vue + axios를 사용하여 비동기 / wait in get 요청을 사용하는 방법 (0) | 2022.07.23 |