简体   繁体   English

使用 AndroidKeyStoreProvider 生成证书签名请求的最佳方法是什么?

[英]What is the best way to generate Certificate Signing Request using AndroidKeyStoreProvider?

I read this article .我读 了这篇文章

It says how to generate a KeyPair , however it doesn't specify how to generate a Certificate Signing Request based on the generated keys.它说明了如何生成KeyPair ,但是它没有指定如何根据生成的密钥生成证书签名请求。

From my research, to generate a CSR in Java, the samples from the web usually use the package sun.* or the BouncyCastle library.根据我的研究,要在 Java 中生成 CSR,web 中的样本通常使用 package sun.*或 BouncyCastle 库。 It seems like there isn't a way to generate a CSR with the standard java.security API. I read this and it seems to say the same thing.似乎没有办法使用标准java.security API 生成 CSR。我读了这篇文章,它似乎在说同样的话。

Do I have no choice but to use BouncyCastle?我别无选择,只能使用 BouncyCastle 吗? It is hard to imagine that Android Developers don't consider this kind of usage.很难想象 Android 开发者不会考虑这种用法。

By the way, the article also mentions that:顺便说一句,文章还提到:

Generating a new PrivateKey requires that you also specify the initial X.509 attributes that the self-signed certificate will have.生成新的私钥还需要您指定自签名证书将具有的初始 X.509 属性。 You can replace the certificate at a later time with a certificate signed by a Certificate Authority您可以稍后将证书替换为由证书颁发机构签名的证书

Suppose I finally get a certificate signed by a Certificate Authority.假设我最终获得了由证书颁发机构签名的证书。 What exactly should I do to "replace the certificate at a later time"?我究竟应该怎么做才能“稍后更换证书”?

Regarding generating a CSR (certificate sign request) on the android phone, I think it is rather straightforward to use Spongycastle instead.关于在 android 手机上生成 CSR(证书签名请求),我认为使用Spongycastle是相当简单的。 It is an android port of Bouncycastle.它是 Bouncycastle 的 android 端口。

Suppose I finally get certificate signed by a Certificate Authority.假设我最终获得了证书颁发机构签署的证书。 What exactly should I do to "replace the certificate at a later time"?我究竟应该怎么做才能“稍后更换证书”?

Once you have the actual signed certificate which you are supposed to get from the CA (Certificate Authority), you no longer need your CSR;一旦您拥有应该从 CA(证书颁发机构)获得的实际签名证书,您就不再需要您的 CSR; you should just store the signed certificate on the phone.您应该将签名证书存储在手机上。 Where to save them - I guess you can get help here .在哪里保存它们 - 我想你可以在这里得到帮助。

The best way to create a CSR on Android is to use SpongyCastle , which is an implementation of BouncyCastle for Android.在 Android 上创建 CSR 的最佳方法是使用SpongyCastle ,它是适用于 Android 的BouncyCastle的实现。 SpongyCastle already does a lot of the heavy-lifting for you so it will make your life much easier. SpongyCastle 已经为你做了很多繁重的工作,所以它会让你的生活更轻松。


My implementation is heavily based on the answer found here , but uses the Android KeyStore for security and SpongyCastle's JcaContentSignerBuilder() instead of the custom ContentSigner .我的实现在很大程度上基于这里找到的答案,但使用 Android KeyStore 来确保安全性和 SpongyCastle 的JcaContentSignerBuilder()而不是自定义ContentSigner

Add SpongyCastle to your build.gradle file:将 SpongyCastle 添加到您的build.gradle文件中:

compile 'com.madgag.spongycastle:core:1.51.0.0'
compile 'com.madgag.spongycastle:pkix:1.51.0.0'

Create the KeyPair in the Android KeyStore :Android KeyStore 中创建 KeyPair :

KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); // store the key in the Android KeyStore for security purposes
keyGen.initialize(new KeyGenParameterSpec.Builder(
                  "key1",
                  KeyProperties.PURPOSE_SIGN)
                  .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                  .setDigests(KeyProperties.DIGEST_SHA256,
                                KeyProperties.DIGEST_SHA384,
                                KeyProperties.DIGEST_SHA512)
                  .build()); // defaults to RSA 2048
KeyPair keyPair = keyGen.generateKeyPair();

Create the CSR using said KeyPair:使用上述 KeyPair 创建 CSR:

private final static String CN_PATTERN = "CN=%s, O=Aralink, OU=OrgUnit";

//Create the certificate signing request (CSR) from private and public keys
public static PKCS10CertificationRequest generateCSR(KeyPair keyPair, String cn) throws IOException, OperatorCreationException {
        String principal = String.format(CN_PATTERN, cn);

        ContentSigner signer = new JcaContentSignerBuilder(DEFAULT_RSA_SIGNATURE_ALGORITHM).build(keyPair.getPrivate());

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

        return csr;
    }
}

And that's it, now you have a PKCS10CertificationRequest that you can send to your server.就是这样,现在您有一个PKCS10CertificationRequest可以发送到您的服务器。

You can use the Bouncy Castle to work with the keys from Android KeyStore.您可以使用 Bouncy Castle 来处理 Android KeyStore 中的密钥。 This doesn't mean that you have to set the Bouncy Castle as a security provider.这并不意味着您必须将 Bouncy Castle 设置为安全提供程序。 It is enough to include the library:包含库就足够了:

implementation 'org.bouncycastle:bcpkix-jdk18on:1.72' 

Note: Spongy Castle is obsolete.注意:海绵城堡已过时。 Standard Bouncy Castle library has to be included in your Android application.标准的 Bouncy Castle 库必须包含在您的 Android 应用程序中。 For details on why see: https://github.com/rtyley/spongycastle/issues/34详细原因见: https://github.com/rtyley/spongycastle/issues/34

val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance(
    KeyProperties.KEY_ALGORITHM_EC,
    "AndroidKeyStore"
)
val keySpecBuilder = KeyGenParameterSpec.Builder(
    Constants.clientCertificateKeyAlias,
    KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
).setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
keyPairGenerator.initialize(keySpecBuilder.build())
val pair = keyPairGenerator.generateKeyPair()

val p10Builder: PKCS10CertificationRequestBuilder = JcaPKCS10CertificationRequestBuilder(
    X500Principal("CN=My Client Certificate"), pair.public
)
val csBuilder = JcaContentSignerBuilder("SHA256withECDSA")
val signer: ContentSigner = csBuilder.build(pair.private)
val csr: PKCS10CertificationRequest = p10Builder.build(signer)

val pemObject = PemObject("CERTIFICATE REQUEST", csr.encoded)
val csrAsString = csrAsStringingWriter()
val pemWriter = PEMWriter(csrAsString)
pemWriter.writeObject(pemObject)
pemWriter.close()
csrAsString.close()
Log.v("CSR", "CSR: $csrAsString")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 java 程序为 ssl 生成证书签名请求 - Generate a Certificate Signing Request for ssl using java program 生成证书签名请求,对其进行签名和验证有哪些选项? - What options are there for generating certificate sign request, signing it and verifying it? 使用Java或BouncyCastle解码/读取CSR(证书签名请求) - Decode/Read a CSR (Certificate Signing Request) Using Java or BouncyCastle 如何使用 Android 上的密钥库创建证书签名请求? - How do you create a Certificate Signing Request using the KeyStore on Android? 产生凭证签署要求的问题 - Issue generating a certificate signing request 让JSF视图生成对非jsf请求的响应的最佳方法是什么? - What's the best way to let a JSF view generate a response to a non-jsf request? Android 上的读/写证书签名请求 (spongycastle) - Read/Write Certificate Signing Request on Android (spongycastle) 使用jstl生成xml的最佳方法 - Best way to generate xml using jstl 确定是使用SHA1算法还是SHA2算法发出证书签名请求 - Determine if certificate signing request was made using SHA1 algorithm or SHA2 algorithm 使用 Reactor WebClient 发出非阻塞 HTTP 请求并反序列化对 object 的响应的最佳方法是什么? - What is the best way to make a non-blocking HTTP request using Reactor WebClient and deserialize the response to an object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM