4

How can i generate CSR from the Key Store.

I have generated CSR from key pair. Below is my code.

public static PKCS10CertificationRequest generateCSR(KeyPair keyPair, String cn) throws IOException,
        OperatorCreationException {
    String principal = String.format(CN_PATTERN, cn);

    ContentSigner signer = new JCESigner (keyPair.getPrivate(),DEFAULT_SIGNATURE_ALGORITHM);

    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());
    Log.e("csr builder ","csr "+csrBuilder.toString());
    PKCS10CertificationRequest csr = csrBuilder.build(signer);

    return csr;
}

But i cannot generate CSR from Keystore(Private Key). Is there any way i can generate key pair from Keystore?

Please help me.Thanks in Advance.

Dante
  • 221
  • 1
  • 3
  • 14
  • Does this answer your question? [What is the best way to generate Certificate Signing Request using AndroidKeyStoreProvider?](https://stackoverflow.com/questions/25907326/what-is-the-best-way-to-generate-certificate-signing-request-using-androidkeysto) – Josh Correia Jul 25 '20 at 05:50

2 Answers2

3

Your code is compatible with Android KeyStore. You just need to generate the KeyPair into the Keystore

The KeyStore is available from Android 4.3 (API level 18). There are slight differences between versions

Android >=18 < 23

KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                .setAlias(alias)
                .setSubject(new X500Principal("CN=" + alias + ", O=Android Authority"))
                .setSerialNumber(BigInteger.ONE)
                .setStartDate(start.getTime())
                .setEndDate(end.getTime())
                .build();

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

kpg.initialize(spec);
KeyPair keyPair = kpg.generateKeyPair();

Android >=23

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");


kpg.initialize(new KeyGenParameterSpec.Builder(
                alias,
                KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                .build());

KeyPair keyPair = kpg.generateKeyPair();
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • 1
    Hi pedrofb , the problem is that i only have the private key, is it possible to generate CSR just from the private key not with the Key pair. – Dante Jul 06 '16 at 06:33
  • No, it is not possible. The CSR must include the public key which is embedded later in the X509Certificate built and signed by your CA. But, I do not understand, a private key is linked with a public key, so if you have the private, you also should have the public – pedrofb Jul 06 '16 at 06:50
  • Actually pedrofb i am generating key pair in Smart card. But due to the security reason i cannot get the key pair value. I only see the Keystore from which i generate the key (KeyStore store = null;store = GPKIKeyStore.getInstance(); store.load(null /* stream unused */, null /* password unused */); aliases = store.aliases();) . Then i generate Key( Key key = store.getKey(alias, null);) So this only conatin the private key. – Dante Jul 06 '16 at 07:02
  • Is there any way i can get the keypair value from the Keystore? – Dante Jul 06 '16 at 07:04
  • The KeyPair is not, but the `java.security.KeyStore` have the private key and the public key you need. Use `PublicKey publicKey = store.getCertificate(alias).getPublicKey()` – pedrofb Jul 06 '16 at 07:15
  • But Pedrofb i don't have any certificate. So there will be no public key. – Dante Jul 06 '16 at 07:26
  • The smartcard should contain the public key in a certificate. How you are connecting to the smart card from android? Will it be through NFC? Surely this manufacturer will be documented in the driver – pedrofb Jul 06 '16 at 07:42
  • I am connecting a smart card with the Bluetooth device and they doesn't deal with CSR only generating key pair in smart card. – Dante Jul 06 '16 at 07:54
  • Ok, I thought you were using a smartcard with a pre built certificate. Then, when you generates the keypair, it should be a way to recover the public key. If not, the cryptographic operation does not make sense. Also, I think my answer does not fit your use case, because you said 'Android' and 'KeyStore' that is the name of Android Keystore System https://developer.android.com/training/articles/keystore.html – pedrofb Jul 06 '16 at 08:18
0

I presume you're talking about java.security.KeyStore. This abstraction requires that each stored PrivateKey has a corresponding chain of Certificate instances (one or more certificate). This means you should be able to create a KeyPair from a private key entry of KeyStore. For example, if the private key is stored under "test":

String alias = "test";
KeyStore keyStore = KeyStore.getInstance(...);
keyStore.load(...;);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null);
PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
KeyPair keyPair = new KeyPair(publicKey, privateKey);
generateCsr(keyPair, ...);
Alex Klyubin
  • 5,554
  • 2
  • 29
  • 24