我在使用自签名证书时遇到问题。我面临例外
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
我将用几句话来描述我的背景:
我正在使用在Raspberry Pi上运行的NodeJS提供的REST服务开发Android应用程序。对于连接,我想使用SSL / TLS来保护连接,即使这个应用程序也只能在本地网络中使用。
所以我的问题是,我无法使用Lets Encrypt来创建证书,因为没有要验证的域,对吧?我的服务器仅在本地运行,没有要验证的域。 因此,我为自己签名的服务器创建了自签名证书。它工作正常,我将证书添加到我的macOS钥匙串,并且连接是安全的。 对于Android,我使用此approach来验证我的自签名证书,但它无效。我通过原始资源包含了服务器的证书。我认为这可能是问题,我必须将歌唱密钥的公钥包含到信任管理器中,而不是服务器证书本身,对吧? 这说我必须创建一个自己的CA?据我所知:我创建一个RSA密钥对并使用私钥签署证书,我的公钥需要包含在TrustManager中,对吗?
我希望有人可以帮助我:)。
编辑:
我获取SSLContext和getStringFromInputStream()
的方法正在按预期工作。
public static SSLContext getSslContext(Context context) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, NoSuchProviderException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
InputStream inputStream = context.getResources().openRawResource(R.raw.keystore);
Certificate certificate;
try {
certificate = certificateFactory.generateCertificate(inputStream);
} finally {
inputStream.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", certificate);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext;
}
AsyncTask打开连接
public class RestRetrieveTask extends AsyncTask<String, Void, String>
{
private Context context;
public RestRetrieveTask(Context context) {
this.context = context;
}
@Override
protected String doInBackground(String... strings) {
String result = null;
try {
SSLContext sslContext = CustomSslCertificateAuthority.getSslContext(context);
URL url = new URL(strings[0]);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
InputStream in = httpsURLConnection.getInputStream();
result = getStringFromInputStream(in);
in.close();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
return result;
}
@Override
protected void onPostExecute(String s) {
System.out.println(s);
}
}
答案 0 :(得分:0)
我通过创建自己的CA并将根证书的公钥添加到密钥库来解决了这个问题。
它的工作就像一个魅力,我只需要创建自己的HostnameVerifier
,因为我没有要验证的主机名。