我有一个pkcs12文件。我需要使用它来使用https协议连接到网页。我遇到了一些代码,为了连接到安全的网页,我需要设置以下系统属性:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", "new_cert.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "newpass");
我有p12(pkcs12)文件。我只需要一个信任库文件。
我使用以下方法提取证书:
openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts
现在将证书PEM文件转换为der
openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der
现在将der文件添加到密钥库
keytool -import -file C:/Cacert.der -keystore mytruststore
现在我有了信任库,但是当我使用它时,我收到以下错误
Exception in thread "main" java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
更新: 删除某些属性并仅设置“trustStore”,“trustStorePassword”和“trustStoreType”属性后,我得到以下异常
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
请帮助。
答案 0 :(得分:21)
对于遇到类似情况的任何人,我能够按如下方式解决上述问题:
按如下方式重新生成pkcs12文件:
openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp
openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd
将CA证书从服务器导入TrustStore(您自己的,或$JAVA_HOME/jre/lib/security/cacerts
中的java密钥库,密码:changeit
)。
设置以下系统属性:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", "new.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "newpasswd");
测试你的网址。
答案 1 :(得分:5)
由于50分阈值,我无法发表评论,但我不认为https://stackoverflow.com/a/537344/1341220中提供的答案是正确的。 您实际描述的是如何将服务器证书插入系统默认信任库:
$JAVA_HOME/jre/lib/security/cacerts, password: changeit)
确实如此,但这意味着您没有真正指定项目本地的信任存储,而是在系统中普遍接受该证书。
您实际上从不使用您在此处定义的自己的信任库:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
答案 2 :(得分:4)
您似乎从PKCS#12密钥库中提取证书并创建新的Java密钥库(类型为“JKS”)。您不必严格提供信任存储密码(尽管使用一个密码可以测试根证书的完整性)。
因此,请尝试使用 以下的SSL属性设置您的程序。您的问题中显示的列表是过度指定的,可能会导致问题。
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
此外,只要将CA证书检测为“受信任”条目,就可以直接将PKCS#12文件用作信任存储。但在这种情况下,您还必须将javax.net.ssl.trustStoreType
属性指定为"PKCS12"
。
仅尝试使用这些属性。如果你得到同样的错误,我怀疑你的问题不是关键商店。如果仍然发生,请在问题中发布更多的堆栈跟踪以缩小问题范围。
新错误“trustAnchors参数必须为非空”可能是由于将javax.net.ssl.trustStore
属性设置为不存在的文件;如果无法打开文件,则会创建一个空的密钥库,这会导致此错误。
答案 3 :(得分:4)
这是一个仅使用p12文件的例子,它没有被优化但是它有效。 由我在OpenSSL生成的pkcs12文件。 示例如何加载p12文件并从中构建Trust区域... 它从p12文件输出证书并向TrustStore添加好的证书
KeyStore ks=KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream("client_t_c1.p12"),"c1".toCharArray());
KeyStore jks=KeyStore.getInstance("JKS");
jks.load(null);
for (Enumeration<String>t=ks.aliases();t.hasMoreElements();)
{
String alias = t.nextElement();
System.out.println("@:" + alias);
if (ks.isKeyEntry(alias)){
Certificate[] a = ks.getCertificateChain(alias);
for (int i=0;i<a.length;i++)
{
X509Certificate x509 = (X509Certificate)a[i];
System.out.println(x509.getSubjectDN().toString());
if (i>0)
jks.setCertificateEntry(x509.getSubjectDN().toString(), x509);
System.out.println(ks.getCertificateAlias(x509));
System.out.println("ok");
}
}
}
System.out.println("init Stores...");
KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "c1".toCharArray());
TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509");
tmf.init(jks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
答案 4 :(得分:1)
此示例显示如何在现有套接字上层叠SSL,从PKCS#12文件获取客户端证书。当您需要通过代理连接到上游服务器并且希望自己处理完整协议时,这是合适的。
然而,基本上,一旦你拥有SSL上下文,你就可以将它应用于HttpsURLConnection等等。
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream is = ...;
char[] ksp = storePassword.toCharArray();
ks.load(is, ksp);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
char[] kp = keyPassword.toCharArray();
kmf.init(ks, kp);
sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(kmf.getKeyManagers(), null, null);
SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) factory.createSocket(socket, socket
.getInetAddress().getHostName(), socket.getPort(), true);
sslsocket.setUseClientMode(true);
sslsocket.setSoTimeout(soTimeout);
sslsocket.startHandshake();
答案 5 :(得分:1)
URL url = new URL("https://test.domain:443");
String keyStore = "server.p12"
String keyStorePassword = "changeit";
String keyPassword = "changeit";
String KeyStoreType= "PKCS12";
String KeyManagerAlgorithm = "SunX509";
String SSLVersion = "SSLv3";
public HttpURLConnection getHttpsURLConnection(URL url, String keystore,
String keyStorePass,String keyPassword, String KeyStoreType
,String KeyManagerAlgorithm, String SSLVersion)
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, FileNotFoundException, IOException,
UnrecoverableKeyException, KeyManagementException {
System.setProperty("javax.net.debug","ssl,handshake,record");
SSLContext sslcontext = SSLContext.getInstance(SSLVersion);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerAlgorithm);
KeyStore ks = KeyStore.getInstance(KeyStoreType);
ks.load(new FileInputStream(keystore), keyStorePass.toCharArray());
kmf.init(ks, keyPassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
sslcontext.init(kmf.getKeyManagers(), tm, null);
SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
HttpsURLConnection httpsURLConnection = ( HttpsURLConnection)uRL.openConnection();
return httpsURLConnection;
}
答案 6 :(得分:1)
以下步骤可帮助您解决问题。
步骤: developer_identity.cer&lt; =从Apple下载 mykey.p12&lt; =您的私钥
要遵循的命令:
openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM
openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem
openssl pkcs12 -export -inkey mykey.pem -in developer_identity.pem -out iphone_dev.p12
我们需要的最终p12是iphone_dev.p12文件和密码。
将此文件用作p12,然后尝试。这确实是解决方案。:)
答案 7 :(得分:0)
我意识到这篇文章可能已经过时但我仍然想请smithsv纠正他的源代码,它包含很多错误,我设法纠正了大部分错误,但仍然不知道x509可能是什么类型的对象。这是我认为应该是的源代码:
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Enumeration;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
public class Connection2 {
public void connect() {
/*
* This is an example to use ONLY p12 file it's not optimazed but it
* work. The pkcs12 file where generated by OpenSSL by me. Example how
* to load p12 file and build Trust zone from it... It outputs
* certificates from p12 file and add good certs to TrustStore
*/
KeyStore ks = KeyStore.getInstance( "pkcs12" );
ks.load( new FileInputStream( cert.pfx ), "passwrd".toCharArray() );
KeyStore jks = KeyStore.getInstance( "JKS" );
jks.load( null );
for( Enumeration t = ks.aliases(); t.hasMoreElements(); ) {
String alias = (String )t.nextElement();
System.out.println( "@:" + alias );
if( ks.isKeyEntry( alias ) ) {
Certificate[] a = ks.getCertificateChain( alias );
for( int i = 0; i == 0; )
jks.setCertificateEntry( x509Cert.getSubjectDN().toString(), x509 );
System.out.println( ks.getCertificateAlias( x509 ) );
System.out.println( "ok" );
}
}
System.out.println( "init Stores..." );
KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
kmf.init( ks, "c1".toCharArray() );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
tmf.init( jks );
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
}
}