min*_*az1 4 java encryption ssl android
我正在使用java的SSLSocket将android应用程序安全地连接到服务器.证书位于信任库中.但是信任库的密码似乎是连接所必需的,因此它当前被硬编码到设备中.我对PKI知之甚少,但这似乎并不安全.我将信任库与原始资源文件夹中的应用程序捆绑在一起.有没有更好的方法来安全地允许应用程序使用TLS连接到服务器?我对TLS/SSL非常新,所以我将不胜感激任何帮助或建议.
这是代码的客户端.
store = KeyStore.getInstance("BKS");
InputStream in = appcontext.getResources().openRawResource(R.raw.truststore);
store.load(in, "PASSWORD".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
tmf.init(store);
sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory sslsocketfactory = sslcontext.getSocketFactory();
// connect to socket
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
"192.168.1.16", 9999);
Run Code Online (Sandbox Code Playgroud)
我没有试过Android,但这是它在普通Java中的工作原理.
您在此处使用密钥库作为信任库,因此(希望)它不包含任何私钥或秘密材料.在这种情况下,密码的目的是验证商店的完整性.
从Keystore.load(InputStream, char[])
文档:
可以给出密码以解锁密钥库(例如,密钥库驻留在硬件令牌设备上),或者检查密钥库数据的完整性.如果没有给出完整性检查的密码,则不执行完整性检查.
您可以使用null
密码(在这种情况下,您始终可以加载证书),或者使用char
带有实际密码的非空数组(在这种情况下,错误的密码将失败,例如" java.io". IOException:Keystore被篡改,或密码不正确 ").
在这里使用密码意味着增加安全性(以防止信任库被篡改).话虽这么说,如果你将这个信任库和这个应用程序捆绑在一起,那么无论如何,能够替换信任库的攻击者也可能获得密码访问权限(通过反编译).(我不太熟悉Android应用程序分发,但如果应用程序已签名,则篡改您的信任库等原始资源也可能使签名无效,因此这可能是一种更现实的方法来获得此保护.否则,我想你可以要求用户每次都输入信任库的密码,但这似乎不切实际.)
这不是您的问题的一部分,但为了保护SSL/TLS连接,您还需要验证服务器发送的证书是否对您尝试访问的主机名有效SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("192.168.1.16", 9999);
.
最近在Java 中的这个问题中对此进行了讨论.(不幸的是,您将无法使用新的Java 7 API在Android上自动执行此操作,因此您必须手动检查证书.您可能也对此最近的问题感兴趣.)
编辑(跟随你的评论):
我担心有人重新编译应用程序,检索密码和信任库并使用它连接到我的服务器.如果有可能那么它首先会破坏TLS的目的.
从这个评论中你不清楚你理解信任库的目的(例如,参见这个问题).
客户端应用程序中信任库的目的不是要向服务器验证您的应用程序,而是确保您的客户端可以验证它连接到的服务器的身份,以便它不会被欺骗连接到服务器MITM攻击者.这不是关于您的服务器如何信任您的应用程序/客户端/用户,而是关于您的应用程序如何信任您的服务器.
将app用户验证到服务器将是密钥库的目的.这对于验证用户来说很好(但是如果每个用户都有不同的证书,那就更有意义了).确保连接只能来自您的应用程序是另一个更困难的问题(如果您无法始终完全控制客户端硬件,则会导致丢失原因).在您的应用程序中使用通用客户端证书可能会给您带来一些时间,但任何掌握了客户端代码的人最终都可以对其进行逆向工程.我不会花太多时间在上面.您可能对以下问题感兴趣:
归档时间: |
|
查看次数: |
1058 次 |
最近记录: |