创建一个HTTPS connecion与客户端证书从PKCS#10,SpongyCastle [英] Creating an Https connecion with Client Side Certificate from PKCS#10 with SpongyCastle

查看:259
本文介绍了创建一个HTTPS connecion与客户端证书从PKCS#10,SpongyCastle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标

我正在实现与客户端证书的通信。

I'm working on implementing communication with Client-Certificate.

第1步:创建PKCS#10请求(CSR),并把它交给我的服务器签名。服务器接触传递CSR的CA和CA的迹象,然后返回一个PKCS#7(与已签署的PKCS#10和CA的证书)。

Step 1: Create a PKCS#10 request (CSR) and give it to the my server for signing. The server contacts passes the CSR to the CA, and the CA signs it, and returns a PKCS#7 (with the signed PKCS#10 and the CA's certificate).

第2步:创建一个PKCS#12,安全地将其存储在Android设备上

Step 2: Create a PKCS#12, store it securely on the Android device

步骤3:创建SSL连接,以使客户机将根据该证书进行认证。

Step 3: Create SSL connection so that the client will be authenticated according to the certificate.

现在,第1步的作品完全使用SpongyCastle 1.50.0.0,但我卡上的其他步骤... 我目前得到一个SSL握手异常,但我得到了,我应该对我实施重新考虑的感觉。

Now, Step 1 works perfectly using SpongyCastle 1.50.0.0, but I'm stuck on the other steps... I'm currently getting an SSL-Handshake exception, but I got the feeling that I should re-think on my implementation.

问题

有谁知道如何实现流量?如何创建和任何真实需要的客户端证书存储与Android的的SSL连接正常工作,以及如何创建这样的SSLContext?

Does anyone know how to implement the flow? How to create and store whatever's needed for a client side certificate to work well with Android's SSLContext, and how to create such SSLContext?

我试过到目前为止

我的第一次尝试是使用钥匙扣,但我们想避免因为那里介绍的用户交互。我的第二个尝试是按照丰富弗里德曼的步骤,但我不知道如何从PKCS#7和私钥创建PKCS#12。对于持久性,我去了<一href="http://www.rahulsingla.com/blog/2011/04/serializing-deserializing-rsa-public-private-keys-generated-using-bouncy-castle-library"相对=nofollow>这个帖子,但(一)这是C#,(B),它是未加密和(c)我认为,Android系统平台拥有更好的按键持久性机制,一说我还一无所知。最后,<一个href="http://chengzhuliulin.word$p$pss.com/2013/08/09/create-pkcs12-from-pem-private-key-file-and-pkcs7-certificate-in-java/"相对=nofollow>这code (用于创建从PEM和PKCS#一个PKCS12 7)没有工作为好,因为我不知道怎么去一个CER文件的剩余部分事情需要。

My first attempt was to use the KeyChain, but we'd like to avoid the user interaction as described there. My second attempt was to follow Rich Freedman's steps, but I don't know how to create a PKCS#12 from the PKCS#7 and the private key. For persistence, I went over this post, but (a) it's C#, (b) it's unencrypted and (c) I think that the android platform has a better keys persistence mechanism, one that I yet know nothing about. Lastly, this code (for creating a PKCS12 from PEM and PKCS#7) didn't work as well, as I didn't know how to get a CER file and the rest of the things it needs.

谢谢!

推荐答案

也许不是最好的code,但它的工作原理,它并没有严格地回答你的问题,但也许你会发现,你可以使用件。

Maybe not the best code, but it works, it does not strictly answer all you questions but maybe you will find pieces you can use.

您的流动性好,我做了几乎同样的事情。

Your flow is good, I'm doing the almost the same thing.

我让我的钥匙在动态创建的密钥库中。 Additionaly我有密钥存储与使用OpenSSL工具创建的受信任的证书。

I'm keeping my keys in dynamically created keystore. Additionaly i have keystore with trusted certificates created with openssl tool.

有关通信我用okHttp +改造

For communication I've used okHttp + retrofit

https://github.com/square/okhttp https://github.com/square/retrofit

生成密钥对

public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);
    KeyPair keyPair = keyPairGenerator.genKeyPair();
    return keyPair;
}

生成CSR:

Generate csr:

private static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair) throws IOException, OperatorCreationException {
    String principal = "CN=company1, OU=company1, O=company1, C=GB";
    AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
    AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder()
            .find("SHA1WITHRSA");
    AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
    ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);

    PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(
            principal), keyPair.getPublic());
    ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
    extensionsGenerator.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true));
    extensionsGenerator.addExtension(X509Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign
            | KeyUsage.cRLSign));
    csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
    PKCS10CertificationRequest csr = csrBuilder.build(signer);

    return csr;
}

发送CSR(您可能需要将其转换为PEM格式),领取证书。

Send csr (you may need to convert it to pem format), receive certificate .

初​​始化密钥库:

KeyStore store = KeyStore.getInstance("BKS");
InputStream in;
try {
    in = App.getInstance().getApplicationContext().openFileInput(filename);
        try {
            store.load(in, password);
        } finally {
            in.close();
        }
    } catch (FileNotFoundException e) {
        //create new keystore
        store.load(null, password);
    }

初​​始化信任库:​​

Init truststore:

KeyStore trustStore = KeyStore.getInstance("BKS");
InputStream in = App.getInstance().getApplicationContext().getResources().openRawResource(R.raw.truststore);
try {
    trustStore.load(in, trustorePassword);
} finally {
    in.close();
}

添加关键密钥库(确保你的私钥和证书的比赛,密钥库不会,如果他们不这样做,抛出异常,并与okHttp这可能会导致的libssl崩溃(仅限于符合API低于4.1)设备:

Add key to keystore (make sure your private key, and certificate match, keystore won't throw exception if they don't, and with okHttp this can cause libssl crashes (only on devices with api below 4.1):

keyStore.setKeyEntry(alias, privateKey, password, new X509Certificate[]{certificate});

与自己创建okHttpClient 的SSL连接

OkHttpClient client = new OkHttpClient();
KeyStore keyStore = App.getInstance().getKeyStoreUtil().getKeyStore();
KeyStore trustStore = App.getInstance().getKeyStoreUtil().getTrustStore();

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyStorePassword);

SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
client.setSslSocketFactory(sslCtx.getSocketFactory());
client.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);

看尼古拉Elenkov博客,你可以找到许多有用的信息与源$ C ​​$ C为好。

Look at Nikolay Elenkov blog, you can find many usefull informations with source code as well.

  • http://nelenkov.blogspot.com/
  • http://nelenkov.blogspot.com/2011/11/using-ics-keychain-api.html
  • http://nelenkov.blogspot.in/2011/12/ics-trust-store-implementation.html
  • http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html
  • http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html
  • http://nelenkov.blogspot.com/2013/08/credential-storage-enhancements-android-43.html

@edit

发表您的异常

@ EDIT2

在你的情况,你需要提取你的 X509证书从web服务的响应,它在密钥库存储与用于生成CSR请求并存储CA证书在另一个密钥库将工作privatekey作为信任库。 (它可以是相同的密钥存储,但它不推荐)。

In your case you need to extract your X509Certificate from webservice response, store it in keystore with privatekey used for generating csr request and store CA cert in another keystore which will work as truststore. (It can be the same keystore, but it's not recommended).

这篇关于创建一个HTTPS connecion与客户端证书从PKCS#10,SpongyCastle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆