Java: BouncyCastleでCSR生成

JavaCSRを作る方法のメモ。BouncyCastleという暗号化APIを使っていきます。

この記事では、コモンネームをtest.comとしたCSRを生成したいと思います。手順としてはこんな感じです。

  1. 電子署名のためのキーペア生成
  2. コモンネーム(test.com)を含むサブジェクト生成
  3. 公開鍵・サブジェクトのセットを秘密鍵で署名
  4. 署名データをPEM形式に変換

以下、動作環境

build.gradleを編集。


dependencies {

    compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.60'
    compile group: 'org.bouncycastle', name: 'bcmail-jdk15on', version: '1.60'
    ...
}

以下、コード。

キーペアの暗号方式はRSA、鍵長は2048bitとしています。

import java.io.IOException;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStrictStyle;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;

public class CsrUtils {
    public static void main(String[] args) throws NoSuchAlgorithmException, OperatorCreationException, IOException{

        System.out.println(generateCsr("c", "test.com"));

    }

    private static String generateCsr(String oid, String value) throws NoSuchAlgorithmException, OperatorCreationException, IOException{

        KeyPair keyPairForSign = generateKeyPairForSign();
        PublicKey publicKey = keyPairForSign.getPublic();
        PrivateKey privateKey = keyPairForSign.getPrivate();

        X500NameBuilder sbjBuilder = new X500NameBuilder(BCStyle.INSTANCE);
        ASN1ObjectIdentifier asnOid = new BCStrictStyle().attrNameToOID(oid);
        sbjBuilder.addRDN(asnOid, value);

        X500Name subject = sbjBuilder.build();

        PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(subject, publicKey);
        PKCS10CertificationRequest csrRequest = generateCsrRequest(csrBuilder, privateKey);


        String pem = parseToPem(csrRequest);

        return pem;
    }

    private static PKCS10CertificationRequest generateCsrRequest(PKCS10CertificationRequestBuilder csrBuilder, PrivateKey privateKey) throws OperatorCreationException {
        JcaContentSignerBuilder jcsBuilder = new JcaContentSignerBuilder("SHA256WITHRSA");
        ContentSigner signer = jcsBuilder.build(privateKey);
        PKCS10CertificationRequest csrRequest = csrBuilder.build(signer);
        return csrRequest;

    }

    private static KeyPair generateKeyPairForSign() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        return keyPair;

    }

    private static String parseToPem(PKCS10CertificationRequest csrRequest) throws IOException {
        StringWriter sw = new StringWriter();
        JcaPEMWriter pemWriter = new JcaPEMWriter(sw);
        pemWriter.writeObject(csrRequest);
        pemWriter.close();
        return sw.toString();

    }
}

無事、生成できました。

-----BEGIN CERTIFICATE REQUEST-----
MIICWDCCAUACAQAwEzERMA8GA1UEBhMIdGVzdC5jb20wggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCBA6WA8tUF7EsLBIfF/8M95hWrrmD+0ysnadMXWA44
fULJexvDo7TKIOPiuI4a37tD5Um+KMJnuB6QPN67uyLMX5AkAP53fIarsz+Y39a2
YAWvGw1hh1QHNbj62T/Z7exhyvUi0BnIZbFoqyxfQecDD4Xdst8RamkssWU2OE6p
GTy6cq/Ta4FNdjoWKlawJNrYoymfwBwoBCtDW/5vN6ppdC4QjKGyOs+T+idd6ohJ
v9NWvzCFecA4viNgX6voAH61WYWvxVKnM/urg7MLia+etOHRe3aeOTH7xFaQ9DMY
N4wqhOsRuarwg3pevpXqvRKp7JRZqYJ986Kwfe5ePNojAgMBAAGgADANBgkqhkiG
9w0BAQsFAAOCAQEAY2JEcLYK/o+Ubn5xkD1zT2+PSL3KSK+XuvN95Qoo/lkgZS0P
+raroGwNm4h/gSLMJmpDo7LE0+A/KmnN/tINTVfXJ7sdFmG2xHtzrZ0HFuXah31v
4K7beprQM20OvB2aZFuNWw+2LCRRla1bGNK2Jxtl7Pu2Hm4pyZ/2o4zHaVdVa+Na
AGRomfrtEjeJr8NxJFXyRF6izp37xyTLPVEF/T0pN0hdDlev65gdKY8QYA88eSxT
/zwa2A34wQ6wklAcVtBb66eA7leqDJF50EkuCYxdHVJhqXtPptDYknP1H8xwu+E4
kt/wFJdeIxVjRpFlAajdy4c1LlQ6/fWgohbF5Q==
-----END CERTIFICATE REQUEST-----

以上、メモでした。