【问题标题】:Wrong version of keystore on android callandroid调用上的密钥库版本错误
【发布时间】:2012-06-22 11:13:06
【问题描述】:

我想发出一个 https 请求。

我使用 bouncycastle 来生成这样的密钥库:

keytool -importcert -trustcacerts -alias ludevCA -file lu_dev_cert.crt -keypass mypass -keystore keystore.bks -storepass mypass -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk15on-146.jar  

并且 keylist 命令返回一个正确的值。

但是当我这样做时:

KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(R.raw.keystore);  
ks.load(in, "mypass".toCharArray());

我有一个错误:

wrong version of keystore

我尝试使用几个版本的 bouncycast,但结果是一样的。我也尝试定义 keysize 1024,但没有任何改变。

有什么想法吗?

【问题讨论】:

  • 不要忘记使用 SHA-256,因为 SHA-1 不再用于 android 23+,默认情况下...

标签: java android certificate bouncycastle keystore


【解决方案1】:

看看Android: Trusting SSL certificates

  -storetype BKS
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider
  -providerpath /path/to/bouncycastle.jar

并在创建密钥库时使用此版本:1.46 版 found here

愿它有帮助...

【讨论】:

  • 这正是我所做的(我再次执行教程)但结果仍然相同。
  • @julesanchez:你必须使用 bcprov-jdk16-146.jar。最新的 v147 会导致上述问题
  • @MarcinOrlowski 这是否意味着我们依赖于 bouncycastle jar?没有我们可以在 android、java、.net 等上使用的标准方法吗?我对此有点困惑。
  • 我可以确认 1.46 产生了正确的 BKS 格式,Android 不接受任何较新的版本。我的版本是 4.2,也许你需要更新的 android 来接受更新版本的 BKS?谁知道?
  • 您应该使用旧的证书版本,而不是使用旧的 bo​​ucycastle 版本。
【解决方案2】:

您需要将密钥库的类型从 BKS 更改为 BKS-v1(BKS-v1 是 BKS 的旧版本)。因为BKS版本改了here

还有另一种解决方案,这要容易得多:

  1. 使用 Portecle:
  1. 您可以使用KeyStore Explorer

新文件将使用 BKS-v1 编码,不再显示错误。要更改 KeyStore 类型,请打开 KeyStore Explorer 并转到 Tools -> Change KeyStore Type,然后保存文件。

注意:
Android 适用于不同的 BKS 版本:例如,API 15 需要 BKS-1,而 API 23 需要 BKS,因此您可能需要将这两个文件都放入您的应用中。

您可以使用此代码根据 API 级别在它们之间切换:

int bks_version;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    bks_version = R.raw.publickey; //The BKS file
} else {
    bks_version = R.raw.publickey_v1; //The BKS (v-1) file
}
KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(bks_version);  
ks.load(in, "mypass".toCharArray());

【讨论】:

  • 似乎解决了我在 4.0.4 设备上遇到的问题,但 4.1.1/2 设备仍然存在同样的问题
  • 不知道为什么,但是当我尝试使用 Portecle 更改它时,它一直不允许我更改密钥库,因为它显示不可恢复的密钥异常。但后来我用 Windows 和 Keystore Explorer 进行了尝试,并从那里更改了密钥库类型,它就像一个魅力。 +1
  • 4.1.1/2 的解决方法:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { ... }
【解决方案3】:

最后我在 Windows 下使用了一个图形编辑器(KeyStore Explorer),它可以工作了。

可能是Java/Mac版本问题导致的错误

【讨论】:

    【解决方案4】:

    解决办法来了,可以去掉版本问题

    为安卓客户端创建 BKS 文件

    创建 BKS 文件所需的软件安装详细信息:

    从链接http://keystore-explorer.sourceforge.net/下载Keystore Explorer软件

    http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html下载UnlimitedJCEPolicyJDK7

    解压 zip 并将 US_export_policy 和 local_policy 复制到您的 C:/programes 文件/java/jre7/lib/security 文件夹中。

    安装 Keystore Explorer 软件。

    生成 BKS 文件的步骤:(需要 CA 文件、证书文件、密钥文件和 .P12 即 PKCS 文件(如果有)。

    1) 使用密钥库软件使用 CA .crt 文件创建信任文件。

    步骤:

    打开软件
    转到文件->新建->从向导中选择 .BKS 导入CA证书文件 进入工具->导入可信证书->选择CA .crt文件->输入密码->(证书为自签名会抛出异常)强制导入文件。

    4.以.bks 扩展名保存文件。

    2) 使用密钥库软件使用 .P12 文件创建密钥文件

    步骤

    打开软件 转到文件->新建->从向导中选择 .BKS

    导入 >p12 文件 Go Tool -> 导入密钥对 -> 从向导中选择 PKCS #12 -> 输入文件和浏览文件的解密密码 -> 输入别名(如果要更改,可以保持原样) - >输入新密码

    以 .bks 扩展名保存文件。

    3) 如果 .P12 不可用,则使用密钥库软件创建密钥文件

    步骤

    打开软件

    Go File->New->从向导中选择 .BKS Import >p12 file Go Tool -> Import key pair -> select OpenSSL from wizard -> unchecked description password for file ,brows .key and .crt (Certificate file not CA) file -> Enter alise name(如果要更改其他可以保持原样)->输入新密码

    以 .bks 扩展名保存文件。

    将两个文件复制到 res/raw 文件夹中(两个 BKS 文件都是强制性的)。

    代码:

     static final String ENABLED_CIPHERS[] = {
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
        "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
        "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
        "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
        "TLS_RSA_WITH_AES_256_CBC_SHA",
        "TLS_RSA_WITH_AES_128_CBC_SHA",
        "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
        "SSL_RSA_WITH_RC4_128_SHA",
        "SSL_RSA_WITH_RC4_128_MD5",
    };
    // put this in a place where it can be reused
    static final String ENABLED_PROTOCOLS[] = {
            "TLSv1.2", "TLSv1.1", "TLSv1"
        };
    
       private void sslCon()
        {
            try {
                                 // setup truststore to provide trust for the server certificate
                  // load truststore certificate
                InputStream trustStoresIs = getResources().openRawResource(R.raw.client_ca);
                String trustStoreType = KeyStore.getDefaultType();
                KeyStore trustStore = KeyStore.getInstance(trustStoreType);
                trustStore.load(trustStoresIs, "spsoft_123".toCharArray());
                //keyStore.setCertificateEntry("ca", ca);
    
                // initialize trust manager factory with the read truststore
                String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                tmf.init(trustStore);
    
                // setup client certificate
                // load client certificate
                InputStream keyStoreStream = getResources().openRawResource(R.raw.client_cert_key);
                KeyStore keyStore = null;
                keyStore = KeyStore.getInstance("BKS");
                keyStore.load(keyStoreStream, "your password".toCharArray());
    
                KeyManagerFactory keyManagerFactory = null;
                keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                keyManagerFactory.init(keyStore, "your password".toCharArray());
    
                // Create an SSLContext that uses our TrustManager
                SSLContext context = SSLContext.getInstance("SSL");
                context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
    
                SSLSocketFactory sslsocketfactory = (SSLSocketFactory)context.getSocketFactory();
                InetAddress serverAddr = InetAddress.getByName("192.168.11.104");
                sslSocket = (SSLSocket) sslsocketfactory.createSocket(serverAddr, 5212);
                //String[] ciphers = sslSocket.getEnabledCipherSuites();
                sslSocket.setEnabledCipherSuites(ENABLED_CIPHERS);
                // put this right before setEnabledCipherSuites()!
                //sslSocket.setEnabledProtocols(ENABLED_PROTOCOLS);
                //InputStream inputStream =  sslSocket.getInputStream();
                OutputStream out = sslSocket.getOutputStream();
    
                Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show();
                sslSocket.close();
    
    
            } catch (KeyManagementException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (CertificateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      我发布此答案是为了提供用于将 .pkcs12 文件转换为 keystore.bks 的 cmdline 版本

      需要什么:

      如果您不知道如何生成 .PKCS12 - 文件,请查看以下网站:

      对于这个示例,我使用jetty.pkcs12 作为源。 该命令生成:keystore.bks /usr/local/share/java/portecle-1.9/ 是我安装下载的 Portecle-Tool (.ZIP) 的路径

      keytool -importkeystore -srckeystore jetty.pkcs12 \
      -srcstoretype PKCS12 -deststoretype BKS -providerpath \
      /usr/local/share/java/portecle-1.9/bcprov.jar -provider \
      org.bouncycastle.jce.provider.BouncyCastleProvider-destkeystore \
      keystore.bks
      

      现在你可以在Android下使用BKS-Keystore

      感谢上一篇文章,我能够找到解决方案并提供此 cmd。希望它可以帮助某人!

      【讨论】:

        【解决方案6】:

        用途:

        KeyStore.getInstance("BKS");
        

        KeyStore.getInstance("PKCS12");
        

        【讨论】:

          猜你喜欢
          • 2015-09-16
          • 1970-01-01
          • 2011-10-19
          • 2013-12-21
          • 2013-05-22
          • 2015-09-13
          • 1970-01-01
          • 2020-11-14
          相关资源
          最近更新 更多