Search code examples
androideclipsecertificatejavacardcsr

How to generate certificate sign request in Android app with public key in Java card


I want to generate certificate for key pair in Java card. I think I should generate pkcs#10 request in the Android app and send it to Java card, but to generate pkcs#10 I need privatekey, but private key is in Java card and shouldn't leave it. How can I do it?


Solution

  • You do not need to extract the private key from Java Card to generate a Certificate Signing Request. Just need to include the public key in the CSR and sign it with the private key.

    Here Certificate enrollment process you can see the general process explained and the involved code for an Android device.

    In your case the process could be like this

    1) The android device gets the public key from the Java Card, builds the CSR and sends the content to Java Card to be signed

    2) The Java Card signs the CSR with the private key 3) The android device sends the signed CSR to server

    4) The server builds the X509 Certificate with the CSR data, signs it with the CA private key and returns the X509 to client

    5) The Android device receives the certificate and sends it to Java Card to be stored

    About the code, the linked example would be valid adding the following modifications

    Create the CSR

    //Necessary to extract the public key from card
    PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(
                    new X500Name(principal), keyPair.getPublic());
    

    The spongycastle JCESigner

    private static class JCESigner implements ContentSigner {
    
        @Override
        public byte[] getSignature() {
            try {
                //MUST be executed in the Java Card. In this point you can 
                //send the outputStream.toByteArray() to the card and sign it with the private key
    
                //signature.update(outputStream.toByteArray());
                //return signature.sign();
            } catch (GeneralSecurityException gse) {
                return null;
            }
        }
    

    The code executed in card to perform the signature would be similar to this one

    Signature signature = Signature.getInstance(sigAlgo);
    signature.initSign(privateKey);
    signature.update(dataToSign);
    byte signedData = signature.sign();