Создание HTTPS-соединения с использованием URL.openConnection()
Я пытаюсь сделать HTTPS-соединение с сервером
В его нынешнем виде это бросает javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
, когда вызывается getOutputStream()
.
Этот же сайт и сертификат действительны на веб-браузере и настольных браузерах HTC. Когда я использую тот же код для доступа к , он работает (но потом жалуется на ошибку 404). Различные сообщения в StackOverflow подразумевают, что он должен "просто работать", а другие говорят, что нужно настроить свой собственный магазин ключей (или отключить всю проверку HTTPS!). Я полагаю, что разница в поведении сводится к использованию различных хранилищ корневых ключей (может ли кто-нибудь уточнить это?).
Теперь я попытался создать хранилище ключей с помощью надувного замка, но я не могу загрузить его на свое устройство.
После экспорта сертификата из Firefox я создаю хранилище ключей, используя:
keytool.exe -import -alias onlinescoutmanager -file www.onlinescoutmanager.co.uk.crt -storetype BKS -keystore res\raw\keystore
Затем он загружается и используется в приложении, используя:
InputStream stream = context.getResources().openRawResource(R.raw.keystore);
// BKS seems to be the default but we want to be explicit
KeyStore ks = KeyStore.getInstance("BKS");
ks.load(stream, "www.onlinescoutmanager.co.uk".toCharArray());
stream.close();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
SSLContext context2 = SSLContext.getInstance("TLS");
context2.init(null, new TrustManager[] { defaultTrustManager }, null);
sslSocketFactory = context2.getSocketFactory();
Это не работает с java.io.IOException: Wrong version of key store.
, когда вызывается keystore.Load()
.
У меня , , добавили сертификаты CA в хранилище ключей и использовали оба Bouncy Castle версии 1.45 и 1.47 для создания хранилища ключей без изменения сообщенного сообщения об ошибке.
Моя среда - Eclipse Juno 4.2.1 с JRE 1.7u9b5, работающая в Windows 8. Устройство, на котором я тестирую, - это сенсация HTC, работающая под управлением Android 2.3. Приложение имеет минимальную версию SDK 7 и целевую 15.
Если кто-нибудь может объяснить, как создать действующее хранилище ключей BKS в Windows 8 или как я могу заставить Java использовать тот же магазин ключей, что и браузер (или система?), который будет оценен.
Вы можете загрузить , как это было на момент написания, и , если требуется.
Ответы
Ответ 1
Bouncy Castle 1.47 использует другой заголовок версии. Можете ли вы попробовать 1.46 version, он должен работать.
keytool -import -alias onlinescoutmanager -file www.onlinescoutmanager.co.uk.crt -storetype BKS -storepass osmosm -keystore C:/keystore -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-ext-jdk15on-1.46.jar
Ответ 2
Благодаря различным людям за их намеки на это, есть несколько вещей, которые должны были быть правильными для его работы.
-
Если сертификат сайта HTTPS подписывается доверенным корневым сертификатом, он будет работать без необходимости использования SSLSocketFactory
.
Доверенные корневые сертификаты могут отличаться от того, что используется браузером, поэтому не предполагайте, что если он будет работать в веб-браузере Android, он будет работать в вашем приложении.
Если это не доверенный корневой сертификат, и вы получаете такие исключения, как javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
, вам необходимо создать и загрузить хранилище ключей, как показано ниже.
-
Ключевой магазин должен быть сгенерирован с использованием поставщика Bouncy Castle (1), указав -storetype bks
в командной строке keytool
.
Если Bouncy Castle установлен неправильно, это приведет к сбою с различными исключениями, включая java.security.KeyStoreException: BKS not found
.
Если хранилище ключей не создано с помощью провайдера Bouncy Castle, вы можете получить исключение java.io.IOException: Wrong version of key store.
, вызывая путаницу со следующим случаем.
-
Вам нужно использовать соответствующую версию (1, 2, 3) поставщика Bouncy Castle. В большинстве случаев это выглядит как версия 1.46.
Это можно поместить в вашу папку JRE lib/ext/
и имя класса, добавленное в lib/security/java.security
, или указав непосредственно в командной строке на keytool
.
Если это несовместимая версия (или тип хранилища), вы снова получите исключения по линиям java.io.IOException: Wrong version of key store.
.
-
Вы должны включить весь посредник и корневой сертификат. Если они отсутствуют, вы получите исключение javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
.
-
Цепочка сертификатов ДОЛЖНА быть для правильной проверки. Если это не так, вы либо получите javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: IssuerName(CN=XYZ) does not match SubjectName(CN=ABC) of signing certificate.
, либо снова, общий javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Я не нашел способ заказать их в хранилище ключей, поэтому прибегал к выполнению этого кода во время выполнения.
Некоторые люди предположили, что с использованием пароля хранилища ключей длиной более 7 символов также приведет к сбою, но это не то, что я нашел.
Я думаю, что это охватывает каждую ловушку, которую я нашел, но не стесняйтесь расширять и добавлять linsk к связанным вопросам.