英文:
Unsafe implementation of the interface X509TrustManager - Google Play
问题
当我尝试将应用上传到Google Play时,我收到一条消息。消息内容是:“不安全实现x509trustmanager接口”。在Google Play的消息中写道:
为了在验证SSL证书时避免问题,请更改X509TrustManager接口中checkServerTrusted方法的代码,以便在检测到可疑证书时抛出CertificateException或IllegalArgumentException。
我找到的所有选项都使用checkValidity方法来验证证书,但Google还补充说:
不要使用checkValidity来验证服务器的证书。此方法检查证书的有效性,而不是其安全性。
我应该如何正确地更改checkServerTrusted方法的代码?我目前的x509TrustManager实现如下:
X509TrustManager trustManager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] cArrr = new X509Certificate[0];
return cArrr;
}
@Override
public void checkServerTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
}
}
@Override
public void checkClientTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
}
};
英文:
When I try to upload an application to google play, I get a message. "Unsafe implementation of the interface x509trustmanager". In a message from Google Play it says:
> To avoid problems when validating the SSL certificate, change the code
> of the checkServerTrusted method in the X509TrustManager interface so
> that a CertificateException or IllegalArgumentException is thrown when
> it detects suspicious certificates.
All the options I've found use the checkValidity method to validate the certificate but Google also adds:
> Do not use checkValidity to validate the server's certificate. This
> method checks the validity of the certificate, not its security.
How can I change the code of the checkServerTrusted method correctly? My current implementation of x509TrustManager:
X509TrustManager trustManager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] cArrr = new X509Certificate[0];
return cArrr;
}
@Override
public void checkServerTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
}
}
@Override
public void checkClientTrusted(final X509Certificate[] chain,
final String authType) throws CertificateException {
}
};
答案1
得分: 2
// 修改了 X509TrustManager 的实现方式,使应用通过了 Google Play 的验证:
TrustManager[] victimizedManager = {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] myTrustedAnchors = new X509Certificate[0];
return myTrustedAnchors;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
if (chain == null || chain.length == 0) throw new IllegalArgumentException("证书为空或者为空");
if (authType == null || authType.length() == 0) throw new IllegalArgumentException("认证类型为空或者为空");
if (!authType.equalsIgnoreCase("ECDHE_RSA") &&
!authType.equalsIgnoreCase("ECDHE_ECDSA") &&
!authType.equalsIgnoreCase("RSA") &&
!authType.equalsIgnoreCase("ECDSA")) throw new CertificateException("证书不被信任");
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("证书无效或不被信任");
}
}
}
};
英文:
I changed the X509TrustManager implementation this way and the app passed Google Play verification:
TrustManager[] victimizedManager = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] myTrustedAnchors = new X509Certificate[0];
return myTrustedAnchors;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
if(chain == null || chain.length == 0)throw new IllegalArgumentException("Certificate is null or empty");
if(authType == null || authType.length() == 0) throw new IllegalArgumentException("Authtype is null or empty");
if(!authType.equalsIgnoreCase("ECDHE_RSA") &&
!authType.equalsIgnoreCase("ECDHE_ECDSA") &&
!authType.equalsIgnoreCase("RSA") &&
!authType.equalsIgnoreCase("ECDSA")) throw new CertificateException("Certificate is not trust");
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate is not valid or trusted");
}
}
}
};
答案2
得分: 1
我之前遇到过这个错误。在我的情况下,以下是修复方法:
private boolean isVerified;
@SuppressLint("TrulyRandom")
public static void handleSSLHandshake() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(final String host, final SSLSession session) {
System.out.print("host" + host+ "\n");
isVerified = host.equalsIgnoreCase(Constants.hostNameVerifierString)
|| host.contains("google") || host.contains("gstatic");
System.out.print(isVerified);
return isVerified;
}
});
} catch (Exception ignored) {
}
}
在需要进行网络调用的活动中,您可以调用 handleSSLHandshake()
方法。或者,如果您使用 Dagger 或任何依赖注入库,您应该能够在任何希望创建网络调用的地方注入它。
Constants.hostNameVerifierString
是我用于网络调用的URL,"google" 和 "gstatic" 被添加是因为我还在使用谷歌地图。
英文:
I've had this error before. In my case, this is what fixed it:
private boolean isVerified;
@SuppressLint("TrulyRandom")
public static void handleSSLHandshake() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(final String host, final SSLSession session) {
System.out.print("host" + host+ "\n");
isVerified = host.equalsIgnoreCase(Constants.hostNameVerifierString)
|| host.contains("google") || host.contains("gstatic");
System.out.print(isVerified);
return isVerified;
}
});
} catch (Exception ignored) {
}
}
In the activity where you have a network call you can call the handleSSLHandshake()
method. Or if you use Dagger or any dependency injection library , you should be able to inject it wherever you want to create network calls.
The Constants.hostNameVerifierString
is the URL I was using for network calls , the "google" and "gstatic" were added because I was also using google maps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论