我想保护我与套接字的SSL连接。但遗憾的是,我的CA证书存在问题。
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:441)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1014)
at com.koushikdutta.async.AsyncSSLSocketWrapper$5.onDataAvailable(AsyncSSLSocketWrapper.java:194)
at com.koushikdutta.async.Util.emitAllData(Util.java:23)
at com.koushikdutta.async.AsyncNetworkSocket.onReadable(AsyncNetworkSocket.java:152)
at com.koushikdutta.async.AsyncServer.runLoop(AsyncServer.java:789)
at com.koushikdutta.async.AsyncServer.run(AsyncServer.java:627)
at com.koushikdutta.async.AsyncServer.access$700(AsyncServer.java:41)
at com.koushikdutta.async.AsyncServer$13.run(AsyncServer.java:569)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:337)
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:231)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
at com.android.org.conscrypt.OpenSSLEngineImpl.verifyCertificateChain(OpenSSLEngineImpl.java:666)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake_bio(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:426)
... 8 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
我的代码:
String type = KeyStore.getDefaultType();
KeyStore trustStore = KeyStore.getInstance(type);
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", new CA().getCert());
String tmfAlg = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlg);
tmf.init(trustStore);
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLEngine engine = context.createSSLEngine();
AsyncSSLSocketWrapper.handshake(socketNormal, url, port, engine, tmf.getTrustManagers(), new NoopHostnameVerifier(), true, (e, socket1) -> {
// ... more
我的证书在我的资产目录中:
public X509Certificate getCert() throws CertificateException, IOException {
CertificateFactory certFactory;
certFactory = CertificateFactory.getInstance("X.509");
InputStream inputStream = new BufferedInputStream(context.getAssets().open("pem.pem"));
return (X509Certificate) certFactory.generateCertificate(inputStream);
}
我的证书是使用私钥签名的,并且是自签名的。
显然,它没有证书工作......但它不安全。
我试图将现有的BKS密钥库放在运行时动态添加:
KeyStore trustStore = KeyStore.getInstance("BKS");
BufferedInputStream is = new BufferedInputStream(c.getAssets().open("key.bks"));
trustStore.load(is, "12345".toCharArray());
Log.i("Cert", "ca " + (new CA().getCert()).getSubjectDN());
String tmfAlg = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlg);
tmf.init(trustStore);
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLEngine engine = context.createSSLEngine();
AsyncSSLSocketWrapper.handshake(socketNormal, url, port,
engine, tmf.getTrustManagers(), new NoopHostnameVerifier(), true, (e, socket1) -> {
但不幸的是,错误是一样的。
编辑2:
更多信息:
服务器PHP使用以下命令生成此证书:
function createSSLCert($pem_file, $pem_passphrase, $pem_dn) {
// //create ssl cert for this scripts life.
//Create private key
$privkey = openssl_pkey_new();
//Create and sign CSR
$cert = openssl_csr_new($pem_dn, $privkey);
$cert = openssl_csr_sign($cert, null, $privkey, 365 * 99);//365
//Generate PEM file
$pem = array();
openssl_x509_export($cert, $pem[0]);
openssl_pkey_export($privkey, $pem[1], $pem_passphrase);
$pem = implode($pem);
//Save PEM file
//echo $pem;
file_put_contents($pem_file, $pem);
//chmod($pem_file, 0600);
}
$pem_passphrase = "XXXXX"; //Set a password here
$pem_file = "cert.pem"; //Set a path/filename for the PEM SSL Certificate which will be created.
//The following array of data is needed to generate the SSL Cert
$pem_dn = array(
"countryName" => "PL", //Set your country name
"localityName" => "City", //Ser your city name
"organizationName" => "Firm name", //Set your company name
"commonName" => "CN", //Set your full hostname.
"emailAddress" => "admin@email.pl" //Set your email address
);
//create ssl cert for this scripts life.
$this->createSSLCert($pem_file, $pem_passphrase, $pem_dn);
Keystore是使用Portecle工具创建的,如: 新 - > BKS - >导入可信证书 - >我的* pem文件 - >保存
openssl s_client -debug -connect 10.100.0.24:5678
返回:
未发送客户端证书CA名称 服务器临时密钥:ECDH,P-256,256位 --- SSL握手读取1630字节并写入451字节 --- 新的,TLSv1 / SSLv3,密码是ECDHE-RSA-AES256-SHA 服务器公钥是2048位 支持安全重新协商 压缩:无 扩展:无 没有ALPN协商
Verify return code: 18 (self signed certificate)
加上一些关于证书的私人信息