Безопасность сообщений с взаимными сертификатами для Android и iOS
Я хотел бы спросить следующее. У нас есть мобильное приложение для Android и iOS, которое обменивается данными с.NET-сервером.
Для Android используется библиотека ksoap2, в то время как для iOS используются Alamofire с библиотеками AEXML.
Мы хотели бы включить шифрование для связи между сервером и приложениями, в частности Message Security с взаимными сертификатами (https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security -with-взаимные сертификаты)
Я не могу найти какую-либо информацию о том, как либо Android, либо iOS-клиент могут шифровать/расшифровывать запросы/ответы.
Можете ли вы предоставить любую относительную информацию?
Заранее спасибо!
Ответы
Ответ 1
Для части iOS.
По умолчанию Alamofire будет оценивать цепочку сертификатов, предоставляемую сервером, используя Apple, встроенную в проверку, предоставляемую инфраструктурой безопасности.
Хотя это гарантирует, что цепочка сертификатов действительна, она не предотвращает атаки типа "человек-в-середине" (MITM) или другие потенциальные уязвимости.
Чтобы смягчить атаки MITM, приложения, относящиеся к конфиденциальным данным клиента или финансовой информации, должны использовать сертификат или публичный ключ, предоставляемый ServerTrustPolicy.
ServerTrustPolicy. Перечисление ServerTrustPolicy оценивает доверие сервера, обычно предоставляемое URLAuthenticationChallenge при подключении к серверу через безопасное соединение HTTPS.
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
)
Существует множество различных случаев оценки доверия к серверу, что дает вам полный контроль над процессом проверки:
performDefaultEvaluation
: использует оценку доверия по умолчанию сервера, позволяя вам контролировать, следует ли проверять хост, предоставленный вызовом.
pinCertificates
: Использует закрепленные сертификаты для проверки доверия сервера. Доверие сервера считается действительным, если один из закрепленных сертификатов соответствует одному из сертификатов сервера.
pinPublicKeys
: Использует закрепленные открытые ключи для проверки доверия сервера.
Доверие к серверу считается действительным, если один из закрепленных открытых ключей соответствует одному из открытых ключей сертификата сервера.
disableEvaluation
: Отключает всю оценку, которая, в свою очередь, всегда будет считать любое доверие сервера действительным.
customEvaluation
: использует связанное закрытие для оценки достоверности доверия к серверу, что дает вам полный контроль над процессом проверки. Используйте с осторожностью.
Документация AlamoFire
Для части Android я не испытываю, но я наткнулся на кого-то, спрашивающего о том же, и получил ответ с
вам нужно только установить сертификат на веб-сервер и вызвать URL-адрес веб- службы, например https://my.webservice.url/, а не http://my.webservice.url/.
Если ваш сертификат является самозаверяющим сертификатом, значит, вы не купили его из центра сертификации, вам необходимо установить SSLSocketFactory. Вы можете проверить вики проекта, как это сделать: http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#How_to_set_the_SSLSocketFactory_on_a_https_connection__in_order
Проверьте здесь.
Это может быть полезно
UPDATE: я нашел эту структуру SOAPEEngine этой. Поддерживает аутентификацию Basic, Digest и NTLM, WS-Security, сертификат на стороне клиента и пользовательский заголовок безопасности.
вы также проверяете его пример для получения дополнительных разъяснений.
Ответ 2
Шифрование сообщений с помощью WCF выполняется через протокол WS-Security, установив mode
атрибута безопасности в Message
. Как вы, несомненно, уже поняли, WS-Security не очень популярна на платформах Android и iOS, в основном из-за того, что она была заменена другими технологиями (например, HTTPS), поэтому ваши варианты с точки зрения существующих библиотек в изобилии. Тот факт, что даже поддерживаемый Microsoft Xamarin не поддерживает, говорит много.
Во-первых, слово WS-Security. Этот протокол предоставляет три основных средства повышения безопасности сообщений:
- Аутентификация через маркеры безопасности
- Подписание сообщений SOAP
- Шифрование сообщений SOAP
Таким образом, соответствующая реализация должна действительно обеспечивать все три из этих функций, но мы в основном заинтересованы в шифровании здесь, так как из вопроса и комментариев кажется, что у вас есть часть аутентификации.
Поэтому, предполагая, что мы ищем библиотеку мобильных платформ, обеспечивающую минимальную совместимость с WCF с подписью и шифрованием WS-Security:
Android
На Android закрытие ваших потребностей - WSS-Client for Android
. Этот проект:
... реализует стандарт OASIS Web Service Security (WSS) для платформ Android и делает XML-шифрование и подпись XML доступными для планшетов и смартфонов.
Обратите внимание, что это программное обеспечение, лицензированное GPL. Readme говорит, чтобы связаться с автором для получения сведений о коммерческой лицензии. Однако, похоже, он делает то, что вы ищете. После того, как вы согласовали обмен ключами с сервером, чтобы зашифровать ранее SOAPUtil
SOAP-сообщение, используя класс SOAPUtil
вы бы сделали что-то вроде:
SOAPMessage message = SOAPUtil.createSOAPMessage();
//... Populate the message (possibly with another library)
SecCrypto serverCrypto = new SecCrypto(serverCertificate, null);
SecCrypto clientCrypto = new SecCrypto(clientPublicKey, clientPrivateKey);
SOAPMessage securedMessage = SOAPUtil.secureSOAPMessage(message, new HashMap<String,String>(SecConstants.REQ_ENCRYPT_SIGN, "yes"), clientCrypto, serverCrypto);
//...
SOAPMessage returnedSecuredMessage = SOAPUtil.sendSOAPMessage(context, securedMessage, endpoint, cryptoParams);
SOAPMessage returnedMessage = SOAPUtil.validateSOAPMessage(returnedSecuredMessage, new HashMap<String,String>(SecConstants.RES_DECRYPT_VERIFY, "yes", decCrypto);
Тем не менее, будьте готовы выполнить небольшую работу по настройке и отладку, чтобы она соответствовала потребностям вашего сервера.
Если вы ищете более современный и активно разработанный продукт, Quasar Development предлагает реализацию WS-Security для Android.
IOS
Вещи выглядят намного более мрачными на стороне iOS. Есть несколько библиотек, требующих различной степени поддержки WSS, но ни один из них не соответствует вашим потребностям:
-
Сначала SOAPEngine выглядит наиболее перспективным, так как он утверждает поддержку WS-Security. Тем не менее, в сноске говорится, что у него есть ограничение, что оно поддерживает только basicHttpBinding
WCF. Это будет нормально, если это правда. Связывание, используемое в примере кода, с которым вы wsHttpBinding
в вопросе, - это wsHttpBinding
однако важно отметить, что как wsHttpBinding
и basicHttpBinding
поддерживают шифрование, хотя WS-Security. Разница в том, что wsHttpBinding
поддерживает WS-Security по умолчанию (тогда как его необходимо включить с помощью basicHttpBinding
), а также поддерживает WS-ReliableMessaging и некоторые другие функции, которые могут вас basicHttpBinding
или нет. Но basicHttpBinding
- это тот, который предназначен для совместимости с другими технологиями. Поэтому, чтобы иметь шифрование WS-Security на вашем сервере WCF и одновременно повысить совместимость с другими технологиями, было бы нормально использовать basicHttpBinding
и включить basicHttpBinding
и шифрование WS-Security, установив атрибут безопасности mode
в Message
. С атрибутом Message
из документов:
Безопасность обеспечивается с помощью безопасности сообщений SOAP. По умолчанию тело зашифровано и подписано. Для этой привязки система требует, чтобы сертификат сервера предоставлялся клиенту вне диапазона. Единственным допустимым типом ClientCredentialType для этого связывания является сертификат.
Но это бесполезно, так как SOAPEngine не поддерживает шифрование сообщений (или, по крайней мере, я не смог найти поддержку в API). Единственная функция WS-Security, которую он поддерживает, - это аутентификация. Поэтому утверждение о том, что он поддерживает WS-Security, кажется ошибочным, поскольку поддержка довольно ограничена.
- ServiceNow предлагает очень ограниченную поддержку WS-Security. Он поддерживает только подтверждение подписей сервера. Нет шифрования или подписания на стороне клиента.
- Chilkat имеет некоторую рудиментарную поддержку XML, и есть образец кода для аутентификации WS-Security. Я не видел никакой поддержки или образца кода для шифрования WS-Security.
Поэтому для iOS, насколько я знаю, ваши два варианта:
- Выберите одну из существующих библиотек, которая наилучшим образом соответствует вашим другим потребностям, и обратитесь к разработчику и посмотрите, можете ли вы добавить их для добавления необходимых функций WS-Security.
- Внедрите минимальные возможности, которые вам нужны сами. Спецификация на самом деле не такая сложная, и там есть образец кода (для немобильных платформ), который вы можете использовать в качестве справочника, например, WSS4J.
Ответ 3
В Android:
Я использую kasoap2 для вызова веб-служб, но перед вызовом для обеспечения взаимной аутентификации с сертификатом клиента вам необходимо инициализировать SSLContext с помощью ключей проверки подлинности клиента (KeyManager). Для этого вам нужно загрузить свой сертификат и соответствующий пароль в объекте KeyStore, мой сертификат - это файл *.pfx. я cerate - экземпляр KeyStore "PKCS12". Затем вам понадобится объект KeyManagerFactory для получения массива KeyManager. Я использую экземпляр KeyManagerFactory "PKIX". Для инициализации SSLContext необходим массив KeyManager.
Вот пример:
public void enableMutualAuthentication(String filename, String password) {
try {
// InputStream to read the certificate file
FileInputStream cert = new FileInputStream(filename);
char[] pass = password.toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(cert ,pass);
cert.close();
KeyManagerFactory keymanagerfactory = javax.net.ssl.KeyManagerFactory.getInstance("PKIX");
keymanagerfactory.init(keystore, pass);
KeyManager[] keymanagers = keymanagerfactory.getKeyManagers();
// This is not for the mutual authentication.
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the mutual authentication manager
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(keymanagers, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
}
Проверьте эти ссылки, что мне больше всего помогает.
https://chariotsolutions.com/blog/post/https-with-client-certificates-on/ http://callistaenterprise.se/blogg/teknik/2011/11/24/android-tlsssl-mutual-authentication/