8

I am looking for a procedure of enrolling a certificate.

I have searched a lot but didn't find a good answer. Till now I get that firstly I have to generate a Key store (For creating a public key and a private key) then private key should be kept private and public key is sent with other information (like name and organization) to the CA. Then the CA will generate something and give me back something which contains the public key and information.

What does the CA generate? What is a P12 file and what does a .cer file contain?

Josh Correia
  • 3,807
  • 3
  • 33
  • 50
Dante
  • 221
  • 1
  • 3
  • 14

2 Answers2

22

The general procedure to issue certificates in a Public Key Infrastructure is more or less the following:

  1. the client generates a key pair, private and public

  2. the client generates a CSR (Certificate Signing Request) including attributes like Common Name and the Public Key. Signs it with the private key and sends it to the server

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

  4. the client stores the private key and the certificate in a KeyStore

What CA generate?

The x509 certificate

What is P12 file

A file in PKCS#12 format (.pfx or .p12) containing a key store

what is .cer file contain

The public part of the certificate (not private key) in DER or PEM format

EDITED - CSR generation on Android

Gradle dependencies

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

Generate KeyPair and CSR

//Generate KeyPair
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyGen.generateKeyPair();

//Generate CSR in PKCS#10 format encoded in DER
PKCS10CertificationRequest csr = CsrHelper.generateCSR(keyPair, commonname);
byte  CSRder[] = csr.getEncoded();

Utilities

public class CsrHelper {

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

  private static class JCESigner implements ContentSigner {

        private static Map<String, AlgorithmIdentifier> ALGOS = new HashMap<String, AlgorithmIdentifier>();

        static {
            ALGOS.put("SHA256withRSA".toLowerCase(), new AlgorithmIdentifier(
                    new ASN1ObjectIdentifier("1.2.840.113549.1.1.11")));
            ALGOS.put("SHA1withRSA".toLowerCase(), new AlgorithmIdentifier(
                    new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")));

        }

        private String mAlgo;
        private Signature signature;
        private ByteArrayOutputStream outputStream;

        public JCESigner(PrivateKey privateKey, String sigAlgo) {
            //Utils.throwIfNull(privateKey, sigAlgo);
            mAlgo = sigAlgo.toLowerCase();
            try {
                this.outputStream = new ByteArrayOutputStream();
                this.signature = Signature.getInstance(sigAlgo);
                this.signature.initSign(privateKey);
            } catch (GeneralSecurityException gse) {
                throw new IllegalArgumentException(gse.getMessage());
            }
        }

        @Override
        public AlgorithmIdentifier getAlgorithmIdentifier() {
            AlgorithmIdentifier id = ALGOS.get(mAlgo);
            if (id == null) {
                throw new IllegalArgumentException("Does not support algo: " +
                        mAlgo);
            }
            return id;
        }

        @Override
        public OutputStream getOutputStream() {
            return outputStream;
        }

        @Override
        public byte[] getSignature() {
            try {
                signature.update(outputStream.toByteArray());
                return signature.sign();
            } catch (GeneralSecurityException gse) {
                gse.printStackTrace();
                return null;
            }
        }
    }

//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 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());
        PKCS10CertificationRequest csr = csrBuilder.build(signer);

        return csr;
    }
}
Josh Correia
  • 3,807
  • 3
  • 33
  • 50
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • A android client is similar but not the same as a Java client. For Android you will need the cryptographic library spongycastle – pedrofb Jun 21 '16 at 11:01
  • Actually i want to Upvote but my reputation is less than 15. I am really sorry for that if i get reputation above 15 my first job is to upvote your answer.And can you please share some link that contains all (server as well as client part).Actually i want complete enrollment of certificate. – Dante Jun 21 '16 at 12:24
  • 1
    Haha. The server part could be difficult and you have to be aware of many considerations. I suggest you to take a look to this opensource project https://www.ejbca.org/ which is a full PKI server written in Java. You can find there all you need. For example, in this class you can found the code to generate a final entity certificate https://www.cesecore.eu/svn/ejbca/tags/Rel_3_0_2/ejbca/src/java/se/anatom/ejbca/ca/caadmin/X509CA.java. After this ask for specific answers in StackOverflow – pedrofb Jun 21 '16 at 12:51
  • 1
    Here you have a link for the specific part of signing a CSR with a CA certificate http://stackoverflow.com/questions/7230330/sign-csr-using-bouncy-castle – pedrofb Jun 21 '16 at 12:58
  • Hi, I read your question and answer and I have questions. How the server get CSR information (Because it was encrypt by private key of client? – ThanhLam112358 Jul 18 '17 at 04:46
  • 1
    CSR is signed, not encrypted, and can be verified using the **public key** of the client, which is also included in the CSR request. There is no hidden information but the digital signature performed with the private key on the CSR ensures integrity and authenticity – pedrofb Jul 18 '17 at 05:56
  • Thank you for your answer. I have one point. I not very clearly about "sign" and "encrypt". What exactly the client do? – ThanhLam112358 Jul 18 '17 at 07:20
  • 1
    Digital signature and encryption are different cryptographic operations (see [this](https://stackoverflow.com/questions/21823679/digital-certificates-what-is-the-difference-between-encrypting-and-signing)) The client generates the key pair, builds the CSR, signs it with the private key and send the CSR to server. I suggest to open a new question if you have additional doubts – pedrofb Jul 18 '17 at 07:37
  • 3
    I'm afraid this site does not work like that. Stack Overflow is a programming site. If you have specific cryptography questions I suggest you ask at https://crypto.stackexchange.com/ or https://security.stackexchange.com/ There are a lot of people out there who know a lot more about cryptography than I do and who will be Delighted to help you – pedrofb Jul 18 '17 at 08:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149452/discussion-between-nistelrooy41001662-and-pedrofb). – ThanhLam112358 Jul 18 '17 at 08:36
  • Hi, I want to generate CSR in android app and I use your code and class CsrHelpler, but how to write it to file .csr. Could you show me? Thank for andvance. – ThanhLam112358 Jul 19 '17 at 16:41
  • Could you use `JcaContentSignerBuilder` rather than implementing `ContentSigner` yourself? – Gibryon Bhojraj Jan 29 '20 at 14:25
  • @GibryonBhojraj Yes, you can. I just posted an answer on this thread with how to do exactly that. – Josh Correia Jul 29 '20 at 20:03
2

To add on to pedrofb's answer you can also use SpongyCastle's JcaContentSignerBuilder instead of JCESigner which will condense your code considerably.

Utilities:

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;
    }
}
Josh Correia
  • 3,807
  • 3
  • 33
  • 50