【问题标题】:What is the best way to hide the keystore password in Android?在 Android 中隐藏密钥库密码的最佳方法是什么?
【发布时间】:2011-11-18 22:57:42
【问题描述】:

我是 Android 开发和实现 SSLSockets 的新手。在进行了一些挖掘之后,我能够设置一个正在工作的简单服务器/客户端。我觉得实现可能需要一些工作,并且在如何将密码加载到密钥库而不使用纯文本时遇到了困难。这是客户端的一些代码。如您所见,我将密码硬编码到本地变量中。有没有更好的方法来加载密钥库密码,所以我在代码中没有纯文本?

    char [] KSPASS = "password".toCharArray();
    char [] KEYPASS = "password".toCharArray();
    try {
        final KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(context.getResources().openRawResource(R.raw.serverkeys), KSPASS);

        final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManager.init(keyStore, KEYPASS);

        final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(keyStore);

        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), null);
        Arrays.fill(KSPASS, ' ');
        Arrays.fill(KEYPASS, ' ');

        KSPASS = null;
        KEYPASS = null;

更新:

事实证明客户端根本不需要知道密钥库密码。我修改了代码以将 null 作为密码传入。到目前为止,初始测试已经与服务器通信。在服务器端,我仍然加载密钥库密码。

        final KeyStore keyStore = KeyStore.getInstance("BKS");
        keyStore.load(context.getResources().openRawResource(R.raw.serverkeys), null);

        final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManager.init(keyStore, null);

        final TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(keyStore);

        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManager.getKeyManagers(), trustFactory.getTrustManagers(), null);

【问题讨论】:

    标签: java android security sockets keystore


    【解决方案1】:

    这不是一个容易开始的问题。

    例如,您可以在应用程序启动时向用户请求密码,这样密码就不会硬编码在您的代码中。我认为这是最安全的方法。

    如果这是不可能的,那么如果有人可以访问 jar 并“看到”代码以及随后的密码,就会出现问题。您可以委托保护这些罐子的用户。

    如果这是不可能的,那么您可以加密密码并将其存储在某个地方。然后在您的代码中,您对密钥进行硬编码以解密密码。因此,查看罐子的人看不到您的真实密码。只有解密密钥。当然,如果付出真正的努力,他可以得到密钥并尝试找到密码所在的位置并对其进行解密并获得密钥,但这需要更多的努力。

    最终取决于您有什么安全要求

    【讨论】:

    • Java 易于反编译和阅读。当您关注呼叫时,您会很快看到那些额外的加密部分。但他可能应该承担风险,因为未加密的网络流比这更危险。
    • 好吧,如前所述,如果攻击者付出额外的努力,他最终可以获得密钥。最好的选择是在启动时询问用户密码。
    • 该评论是为提问者提供的附加信息。我应该指出这一点。
    • 让我澄清一下。这不是用户会知道的密码。这个想法是没有从客户端到服务器的纯文本传输。所以我使用命令 keytool 创建一个证书,给它一个密钥库密码并添加一个密钥并给它另一个密码。该应用程序没有发送敏感数据,但我仍然不想要纯文本。签署 Android 应用程序是否会使其更难反编译?
    • 即使你混淆了代码,你的程序中的各种常量变量也应该是可见的(否则你的程序将无法运行)。你可以结合密码加密然后混淆代码。但是你还必须考虑在哪里/如何存储解密密钥
    【解决方案2】:

    如果您真的想保护用户凭据,那么您必须在您想要访问凭据时要求他们验证其身份。但是,如果您每次登录时都向他们询问密码,大多数用户会感到恼火,因此作为开发人员,您必须决定您对安全性的关注程度,还是为您的用户提供简单易用的界面。

    您可以考虑的一种选择是存储密码,但使用用户提供的 PIN 对密码进行加密。然后,每当用户想要访问他们的密码时,他们只需提供用于解密密码的 PIN。

    【讨论】:

    • 此 PIN 存储在哪里?
    猜你喜欢
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 2011-05-20
    • 2011-03-29
    • 2022-01-25
    • 2016-11-20
    • 2013-01-19
    • 1970-01-01
    相关资源
    最近更新 更多