我想问以下问题。我们有一个适用于Android和iOS的移动应用程序,可与.NET服务器交换数据。
对于Android,使用ksoap2库,而对于iOS,则使用带有AEXML库的Alamofire。
我们希望为服务器和应用之间的通信启用加密,特别是带有互证书(https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-with-mutual-certificates)的邮件安全性
我无法找到有关Android或iOS客户端如何加密/解密请求/响应的任何信息。
请提供任何相关信息?
谢谢!
答案 0 :(得分:3)
对于iOS部分。
默认情况下,Alamofire将使用安全框架提供的Apple内置验证来评估服务器提供的证书链。
尽管这可以确保证书链有效,但不能防止中间人(MITM)攻击或其他潜在漏洞。
为了减轻MITM攻击,处理敏感客户数据或财务信息的应用程序应使用ServerTrustPolicy提供的证书或公钥固定。
ServerTrustPolicy 通过安全HTTPS连接连接到服务器时,ServerTrustPolicy枚举会评估通常由URLAuthenticationChallenge提供的服务器信任。
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
)
服务器信任评估有许多不同的情况,使您可以完全控制验证过程:
performDefaultEvaluation
:使用默认的服务器信任评估,同时允许您控制是否验证质询提供的主机。
pinCertificates
:使用固定证书来验证服务器信任。如果固定证书之一与服务器证书之一匹配,则服务器信任被视为有效。
pinPublicKeys
:使用固定的公钥来验证服务器信任。
如果固定的公用密钥之一与服务器证书公用密钥之一匹配,则服务器信任被视为有效。
disableEvaluation
:禁用所有评估,这反过来将始终将任何服务器信任视为有效。
customEvaluation
:使用关联的闭包来评估服务器信任的有效性,从而使您可以完全控制验证过程。谨慎使用。
AlamoFire documentation
对于Android而言,我并不熟悉,但是遇到了有人问同样的事情,并且得到了答案
您需要做的只是将证书安装到Web服务器中,然后调用https://my.webservice.url/之类的Web服务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以获得更多说明。
答案 1 :(得分:3)
使用WS-Security协议通过将安全属性mode
设置为Message
,可以使用WCF进行消息加密。毫无疑问,到目前为止,WS-Security在Android和iOS平台上并不十分流行,主要是因为它已被其他技术(例如HTTPS)所取代,因此您在现有库方面的选择并不多。 not even Microsoft-owned Xamarin supports it讲了很多话。
首先,它是WS-Security的缩写,该协议提供了三种增强消息安全性的主要方法:
因此,一个合规的实现实际上应该提供所有这三个功能,但是我们在这里最感兴趣的是加密,因为从问题和注释看来,您的身份验证部分正在起作用。
因此,假设我们正在寻找一个提供最少的WCF与WS-Security签名和加密兼容性的移动平台库:
在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方面的情况看起来更加暗淡。有一些图书馆声称对WSS的支持程度不同,但是似乎都不符合您的需求:
起初SOAPEngine看起来最有希望
支持WS-Security。但是,在脚注中说它有一个
仅支持WCF basicHttpBinding
的限制。这个
如果为true,则实际上可以。您在示例代码中使用的绑定
问题中链接到的是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是证书。
但这没有用,因为SOAPEngine不支持 加密消息(或者至少我找不到对此的任何支持) 在API中)。它支持的唯一WS-Security功能是 身份验证。因此,声称它支持WS-Security的说法似乎 误导,因为支持非常有限。
因此,就我所知,对于iOS,您有两个选择:
答案 2 :(得分:0)
在Android中:
我使用kasoap2调用Web服务,但是在调用之前,要启用与客户端证书的相互身份验证,您需要使用客户端身份验证密钥(KeyManager)初始化SSLContext。 为此,您必须在KeyStore对象中加载证书和相应的密码,我的证书是* .pfx文件。我确定了一个“ PKCS12” KeyStore实例。然后,您需要一个KeyManagerFactory对象来获取KeyManager数组。我使用“ PKIX” KeyManagerFactory实例。需要KeyManager数组来初始化SSLContext。
这里是一个例子:
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/