36

我想发出一个 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,但没有任何改变。

有任何想法吗 ?

4

6 回答 6

33

看看它Android:信任 SSL 证书

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

并在创建密钥库时使用此版本:版本 1.46 在这里找到

愿它有帮助...

于 2012-06-20T10:57:39.500 回答
29

您需要将密钥库的类型从 BKS 更改为 BKS-v1(BKS-v1 是 BKS 的旧版本)。因为BKS版本如这里所说改变了

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

  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());
于 2015-10-18T12:19:40.013 回答
5

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

可能该错误是由 Java/Mac 版本问题引起的

于 2012-06-27T14:05:35.977 回答
3

解决方案在这里,能够删除版本问题

为android客户端创建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 iePKCS 文件(如果有)。

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

脚步:

打开软件
Go File->New->从向导中选择.BKS 导入CA证书文件Go Tool->Import trust certificate->选择CA .crt文件->输入密码->(如果证书是self会抛出异常签名)强制导入文件。

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

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

脚步

打开软件Go File->New->从向导中选择.BKS

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

以 .bks 扩展名保存文件。

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

脚步

打开软件

转到文件->新建->从向导中选择 .BKS 导入 >p12 文件转到工具 -> 导入密钥对 -> 从向导中选择 OpenSSL ->未选中文件的解密密码,浏览 .key 和 .crt(证书文件不是 CA)文件 -> 输入别名(如果要更改,可以保持原样) -> 输入新密码

以 .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();
        }

    }

}
于 2014-01-10T08:34:09.233 回答
1

我发布这个答案是为了提供一个用于将.pkcs12文件转换为的 cmdline-versionkeystore.bks

需要什么:

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

对于此示例,我将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。希望它可以帮助某人!

于 2017-01-02T12:58:31.707 回答
0

采用:

KeyStore.getInstance("BKS");

或者

KeyStore.getInstance("PKCS12");
于 2018-05-13T08:24:11.993 回答