Поиск подписи SSL-сертификата
Я новичок в Android. Я написал код для IOS и хочу аналогичный алгоритм в Android.
Вот сцена. У меня есть 2 типа серверов - 1. с самоподписанным сертификатом 2. с подписанным сертификатом.
Теперь в IOS я использую следующие шаги, чтобы решить, подписан он или нет.
STACK_OF (X509) * stX509Certificate = SSL_get_peer_cert_chain (ssl); int cert_num = sk_X509_num (stX509Certificate);
CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, cert_num, NULL);
for (int i = 0; i < cert_num; i++) {
unsigned char *raw = NULL;
X509 *x509Certificate = sk_X509_value(stX509Certificate, i);
int rawlen = i2d_X509(x509Certificate, &raw);
CFDataRef cfcert = CFDataCreate(NULL, raw, rawlen);
free(raw);
SecCertificateRef secCertRef = SecCertificateCreateWithData(NULL, cfcert);
CFRelease(cfcert);
CFArrayAppendValue(certArray, secCertRef);
}
CFStringRef servAddr = CFStringCreateWithCString(NULL, [[srvSplit objectAtIndex:0] cStringUsingEncoding:NSUTF8StringEncoding], kCFStringEncodingUTF8);
SecPolicyRef secPolRef = SecPolicyCreateSSL(YES, servAddr);
CFRelease(servAddr);
SecTrustRef secTruRef ;
SecTrustResultType secTrustRes;
Boolean isCertTrusted = NO;
if(SecTrustCreateWithCertificates(certArray, secPolRef, &secTruRef) == errSecSuccess) {
SecTrustSetAnchorCertificatesOnly(secTruRef, NO);
if (SecTrustEvaluate(secTruRef,&secTrustRes) == errSecSuccess) {
switch (secTrustRes) {
case kSecTrustResultInvalid:
case kSecTrustResultDeny:
case kSecTrustResultRecoverableTrustFailure:
case kSecTrustResultFatalTrustFailure:
case kSecTrustResultOtherError:
isCertTrusted = NO;
break;
case kSecTrustResultUnspecified:
case kSecTrustResultProceed:
isCertTrusted = YES;
break;
}
}
}
В андроиде не могу найти такой TrustEvaluate
метод. Я старался getBasicConstraints
а также getKeyUsage
, Но я не могу отличить подписанные и другие сертификаты.
Пожалуйста, помогите мне.
1 ответ
Попробуйте этот код, он может не совпадать с вашим алгоритмом IOS, но работает нормально.
- Добавьте свой собственный сертификат в /res/raw
- Сначала этот код проверяет системные сертификаты Android (доверенные учетные данные), в этом случае, если вы подключаетесь к сертифицированному CA-серверу, он проверяет ваш сертификат и позволяет подключиться к серверу.
- Если вы пытаетесь подключить самоподписанный сервер, он проверяет ваш самоподписанный сертификат, который находится в /res/raw
Если вы пытаетесь подключить самозаверяющий сервер с IP-адресом, тогда ваш сертификат должен содержать subjectAltName
public class CheckCertificate{ private static class NewCustomTrustManager implements X509TrustManager{ private X509TrustManager defaultTrustManager; private X509TrustManager localTrustManager; public NewCustomTrustManager(KeyStore localKeyStore) throws KeyStoreException { try { this.defaultTrustManager = createNewTrustManager(null); this.localTrustManager = createNewTrustManager(localKeyStore); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } private X509TrustManager createNewTrustManager(KeyStore store) throws NoSuchAlgorithmException, KeyStoreException { String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(store); TrustManager[] trustManagers = tmf.getTrustManagers(); return (X509TrustManager) trustManagers[0]; } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { //Checks system certificate defaultTrustManager.checkServerTrusted(chain, authType); } catch (CertificateException ce) { //Checks your self signed certificate localTrustManager.checkServerTrusted(chain, authType); } } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { X509Certificate[] first = defaultTrustManager.getAcceptedIssuers(); X509Certificate[] second = localTrustManager.getAcceptedIssuers(); X509Certificate[] result = Arrays.copyOf(first, first.length + second.length); return result; } } public static void setCustomCertificate(Context cn) { try { // Load CAs from an InputStream // (could be from a resource or ByteArrayInputStream or ...) CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = new BufferedInputStream(cn.getResources().openRawResource(R.raw.apache_25)); try { ca = cf.generateCertificate(caInput); }catch (Exception e){ e.printStackTrace(); }finally { caInput.close(); } // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("cacertificate", ca); // Create a TrustManager that trusts the CAs in our KeyStore and system CA NewCustomTrustManager trustManager = new NewCustomTrustManager(keyStore); // Create an SSLContext that uses our TrustManager SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[]{trustManager}, null); // Tell the URLConnection to use a SocketFactory from our SSLContext HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }