Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you generate a CSR in Java without signing it by the requester?

Basically, I need to isolate the data of the constructed CSR (Certificate Signing Request) prior to it being first signed by the entity making the request, preferably in Java. Many thanks in advance!

It would also be useful to note how to subsequently append the signature to the CSR as the CSR data will be initially signed by an HSM.

like image 751
penguin4hire Avatar asked Nov 17 '11 00:11

penguin4hire


People also ask

Do you need a private key to generate a CSR?

Certificate signing requests (CSR) are generated with a pair of keys – a public and private key. Only the public key is sent to a Certificate Authority and included in the SSL certificate, and it works together with your private key to encrypt the connection.


2 Answers

I hope this helps:

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;


import javax.security.auth.x500.X500Principal;

import sun.security.pkcs10.*;
import sun.security.x509.*;

public class GenerateCSR {
    private static PublicKey publicKey = null;
    private static PrivateKey privateKey = null;
    private static KeyPairGenerator keyGen = null;
    private static GenerateCSR gcsr = null;

    private GenerateCSR() {
        try {
            keyGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.initialize(2048, new SecureRandom());
        KeyPair keypair = keyGen.generateKeyPair();
        publicKey = keypair.getPublic();
        privateKey = keypair.getPrivate();
    }

    public static GenerateCSR getInstance() {
        if (gcsr == null)
            gcsr = new GenerateCSR();
        return gcsr;
    }

    public String getCSR(String cn) throws Exception {
        byte[] csr = generatePKCS10(cn, "Java", "JournalDev", "Cupertino",
                "California", "USA");
        return new String(csr);
    }

    /**
     *
     * @param CN
     *            Common Name, is X.509 speak for the name that distinguishes
     *            the Certificate best, and ties it to your Organization
     * @param OU
     *            Organizational unit
     * @param O
     *            Organization NAME
     * @param L
     *            Location
     * @param S
     *            State
     * @param C
     *            Country
     * @return
     * @throws Exception
     */
    private static byte[] generatePKCS10(String CN, String OU, String O,
            String L, String S, String C) throws Exception {
        // generate PKCS10 certificate request
        String sigAlg = "MD5WithRSA";
        PKCS10 pkcs10 = new PKCS10(publicKey);
        Signature signature = Signature.getInstance(sigAlg);
        signature.initSign(privateKey);
        // common, orgUnit, org, locality, state, country
        X500Principal principal = new X500Principal( "CN=Ole Nordmann, OU=ACME, O=Sales, C=NO");

   //     pkcs10CertificationRequest kpGen = new PKCS10CertificationRequest(sigAlg, principal, publicKey, null, privateKey);  
     //   byte[] c = kpGen.getEncoded();  
        X500Name x500name=null;
        x500name= new X500Name(principal.getEncoded());
      pkcs10.encodeAndSign(x500name, signature);
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(bs);
        pkcs10.print(ps);
        byte[] c = bs.toByteArray();
        try {
            if (ps != null)
                ps.close();
            if (bs != null)
                bs.close();
        } catch (Throwable th) {
        }
        return c;
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    public static void main(String[] args) throws Exception {
        GenerateCSR gcsr = GenerateCSR.getInstance();

        System.out.println("Public Key:\n"+gcsr.getPublicKey().toString());

        System.out.println("Private Key:\n"+gcsr.getPrivateKey().toString());
        String csr = gcsr.getCSR("journaldev.com <http://www.journaldev.com>");
        System.out.println("CSR Request Generated!!");
        System.out.println(csr);
    }

}
like image 148
Desphilboy Avatar answered Oct 03 '22 08:10

Desphilboy


I used the Bouncy Castle libraries to produce a certificate request without signing it. The problem I was facing was that a lot of applications available to generate a CSR took care of both generating it AND signing it. I only wanted to produce an unsigned CSR. Unfortunately, I cannot divulge the code used to produce the unsigned CSR due to company policy but I have listed many hints below that should help others. Here are some steps that might aid someone else trying to do the same thing:

  1. Look at example CSR data generated with openssl or some other tool using the following website.

    http://lapo.it/asn1js/

    This site even includes an example certificate object to see it in action.

  2. Become familiar with ASN1 encoding. This is how certificate data is encoded and you will need to encode the CSR similarly using Bouncy Castle.

  3. Use Bouncy Castle to produce the CSR data. Here is a code snippet on initializing some of the fields typically found in CSR data.

    // Create Organization Name<br/>
    DERObjectIdentifier oidOrgName     = new DERObjectIdentifier("2.5.4.10");
    DERPrintableString  prntstrOrgName = new DERPrintableString("Test Organization");
    DERSet              setOrgName     = new DERSet(new DERSequence(new ASN1Encodable[] {oidOrgName, prntstrOrgName}));
    
    // Create org unit name
    DERObjectIdentifier oidOrgUnitName     = new DERObjectIdentifier(2.5.4.11);
    DERPrintableString  prntstrOrgUnitName = new DERPrintableString("Org Unit Name");
    DERSet              setOrgUnitName     = new DERSet(new DERSequence(new ASN1Encodable[] {oidOrgUnitName, prntstrOrgUnitName}));
    
like image 26
penguin4hire Avatar answered Oct 03 '22 09:10

penguin4hire