适用于 Android 和 iOS 的具有相互证书的消息安全性
Posted
技术标签:
【中文标题】适用于 Android 和 iOS 的具有相互证书的消息安全性【英文标题】:Message Security with Mutual Certificates for Android & iOS 【发布时间】:2019-02-24 22:42:06 【问题描述】:我想问以下问题。我们有一款适用于 android 和 ios 的移动应用,可与 .NET 服务器交换数据。
Android 使用 ksoap2 库,而 iOS 使用 Alamofire 和 AEXML 库。
我们希望为服务器和应用程序之间的通信启用加密,特别是带有相互证书的消息安全 (https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-with-mutual-certificates)
我无法找到任何关于 Android 或 iOS 客户端如何加密/解密请求/响应的信息。
您能否提供任何相关信息?
提前致谢!
【问题讨论】:
你的意思是加密请求的正文? 不,整条消息都基于这个en.wikipedia.org/wiki/WS-Security 【参考方案1】:对于 iOS 部分。
默认情况下,Alamofire 将使用安全框架提供的 Apple 内置验证来评估服务器提供的证书链。
虽然这保证了证书链是有效的,但它并不能防止中间人 (MITM) 攻击或其他潜在漏洞。
为了减轻 MITM 攻击,处理敏感客户数据或财务信息的应用程序应使用 ServerTrustPolicy 提供的证书或公钥固定。
服务器信任策略 当通过安全的 HTTPS 连接连接到服务器时,ServerTrustPolicy 枚举评估通常由 URLAuthenticationChallenge 提供的服务器信任。
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
)
有许多不同的服务器信任评估案例让您可以完全控制验证过程:
performDefaultEvaluation
:使用默认的服务器信任评估,同时允许您控制是否验证挑战提供的主机。
pinCertificates
:使用固定证书来验证服务器信任。如果固定证书之一与服务器证书之一匹配,则认为服务器信任有效。
pinPublicKeys
:使用固定的公钥来验证服务器信任。
如果固定的公钥之一与服务器证书公钥之一匹配,则认为服务器信任有效。
disableEvaluation
:禁用所有评估,这反过来将始终将任何服务器信任视为有效。
customEvaluation
:使用关联的闭包来评估服务器信任的有效性,从而让您完全控制验证过程。谨慎使用。
阿拉莫火documentation
对于Android部分,我没有经验,但我遇到有人问同样的事情并得到了答案
您需要做的只是将您的证书安装到网络服务器中并调用网络服务 URL,如 https://my.webservice.url/ 而不是 http://my.webservice.url/。
如果您的证书是自签名证书,则意味着您没有 从证书颁发机构购买的,您需要设置 SSLSocketFactory。您可以查看项目 wiki 以了解如何执行此操作: http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#How_to_set_the_SSLSocketFactory_on_a_https_connection__in_order
检查Here。
This 可能也很有帮助
更新:我找到了这个框架SOAPEEngine 这个。 支持基本、摘要和 NTLM 身份验证、WS-Security、客户端证书和自定义安全标头。
您也可以查看example 以获得更多说明。
【讨论】:
感谢您与我们联系。但是我面临的问题与消息的加密部分有关。现有 API 使用用户名密码安全机制以及证书固定等,但为了提高安全性,必须在发送前对整个消息进行加密。 您好,感谢您的反馈。我知道这个库,但您可以检查限制:“对于 WCF 服务,仅支持基本的 http 绑定 (basicHttpBinding)。”而不是 wsHttpBinding。【参考方案2】:使用 WCF 的消息加密是通过 WS-Security 协议完成的,方法是将安全属性 mode
设置为 Message
。毫无疑问,您现在已经意识到,WS-Security 在 Android 和 iOS 平台上并不完全流行,主要是因为它已被其他技术(如 HTTPS)取代,因此您在现有库方面的选择并不丰富。 not even Microsoft-owned Xamarin supports it 这个事实说明了很多。
首先,关于 WS-Security,该协议提供了三种主要的增强消息安全性的手段:
通过安全令牌进行身份验证 签署 SOAP 消息 SOAP 消息的加密因此,符合要求的实现应该真正提供所有这三个功能,但我们对这里的加密最感兴趣,因为从问题和 cmets 看来,您的身份验证部分正在工作。
因此,假设我们正在寻找一个提供与 WS-Security 签名和加密的最小 WCF 兼容性的移动平台库:
安卓
在 Android 上,最接近您的需求是 WSS-Client for Android
。本项目:
... 实现了 OASIS Web 服务安全 (WSS) 标准 Android 平台并使 XML 加密和 XML 签名可用 适用于平板电脑和智能手机。
请注意,这是 GPL 许可软件。自述文件说要联系作者以获取商业许可的详细信息。但是,它似乎可以满足您的要求。与服务器协商密钥交换后,要使用 SOAPUtil
类加密先前构建的 SOAP 消息,您可以执行以下操作:
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 提供了适用于 Android 的 WS-Security 实现。
iOS
iOS 方面的情况看起来要黯淡得多。有几个库声称对 WSS 的支持程度不同,但似乎没有一个库能满足您的需求:
一开始SOAPEngine 看起来最有希望,正如它所声称的那样
支持 WS-Security。然而,在一个脚注中它说它有一个
限制它只支持 WCF basicHttpBinding
。这
如果属实,实际上会没问题。您在示例代码中使用的绑定
问题中的链接是wsHttpBinding
,但这很重要
注意wsHttpBinding
和basicHttpBinding
都有支持
通过 WS-Security 进行加密。不同之处在于
wsHttpBinding
默认支持 WS-Security(而它需要
启用basicHttpBinding
),它还支持
WS-ReliableMessaging 和 some other features 你可能会也可能不会
关心。但是basicHttpBinding
是用于
与其他技术的兼容性。所以为了拥有
WCF 服务器上的 WS-Security 加密并最大限度地提高兼容性
与其他技术同时使用,就可以了
basicHttpBinding
并通过以下方式启用 WS-Security 签名和加密
将mode
安全属性设置为Message
。随着
Message
属性,from the docs:
使用 SOAP 消息安全性提供安全性。默认情况下,正文 已加密和签名。对于此绑定,系统要求 服务器证书以带外方式提供给客户端。唯一的 此绑定的有效 ClientCredentialType 是 Certificate。
但这没有用,因为 SOAPEngine 不支持 加密消息(或者至少我找不到任何支持它 在 API 中)。它支持的唯一 WS-Security 功能是 验证。所以它支持 WS-Security 的说法似乎 由于支持非常有限,因此具有误导性。
ServiceNow 对 WS-Security 的支持非常有限。它只是 支持验证服务器签名。没有加密或签名 客户端。 Chilkat 有一些基本的 XML 支持,并且有示例 WS-Security 身份验证的代码。我没有看到任何支持或 WS-Security 加密的示例代码。因此,据我所知,对于 iOS,您的两个选择是:
选择最符合您其他需求的现有库之一 并联系开发人员,看看您是否可以让他们添加 您需要的 WS-Security 功能。 实现最低限度的功能 你需要你自己。 The spec 其实没那么复杂 那里有示例代码(适用于非移动平台),您 可以用作指南,例如 WSS4J。【讨论】:
【参考方案3】:在安卓中:
我使用 kasoap2 调用 Web 服务,但在调用之前,要启用与客户端证书的相互身份验证,您需要使用客户端身份验证密钥 (KeyManager) 初始化 SSLContext。 为此,您必须在 KeyStore 对象中加载您的证书和相应的密码,我的证书是一个 *.pfx 文件。我创建了一个“PKCS12”KeyStore 实例。然后你需要一个 KeyManagerFactory 对象来获取 KeyManager 数组。我使用“PKIX” KeyManagerFactory 实例。初始化 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/
【讨论】:
以上是关于适用于 Android 和 iOS 的具有相互证书的消息安全性的主要内容,如果未能解决你的问题,请参考以下文章
一个自签名证书来统治他们? Chrome、Android 和 iOS
我正在使用 `fcm` gem 发送推送通知,它适用于 android 但不适用于 IOS
适用于 ios 的 Android 应用程序包(动态功能)?