3

Spongy Castle (v1.47) を使用して PKCS10 認証要求を作成しようとしています。Spongy Castle は Bouncy Castle とまったく同じように動作しますが、Android への移植により適しています。

第 6 章の David Hook による Beginning Cryptography with Java で説明されている古い (廃止された) 方法は問題なく機能します。

package chapter6;

import java.io.OutputStreamWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.util.Vector;
import javax.security.auth.x500.X500Principal;
import org.spongycastle.asn1.DEROctetString;
import org.spongycastle.asn1.DERSet;
import org.spongycastle.asn1.pkcs.Attribute;
import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.spongycastle.asn1.x509.GeneralName;
import org.spongycastle.asn1.x509.GeneralNames;
import org.spongycastle.asn1.x509.X509Extension;
import org.spongycastle.asn1.x509.X509Extensions;
import org.spongycastle.jce.PKCS10CertificationRequest;
import org.spongycastle.openssl.PEMWriter;
import org.spongycastle.jce.provider.BouncyCastleProvider;

/**
 * Generation of a basic PKCS #10 request with an extension.
 */
public class PKCS10ExtensionExample {
  static {
    BouncyCastleProvider prov = new org.spongycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(prov);
  }

  public static PKCS10CertificationRequest generateRequest( KeyPair pair) throws Exception {
    // create a SubjectAlternativeName extension value
    GeneralNames subjectAltName = new GeneralNames(new GeneralName(GeneralName.rfc822Name, "test@test.test"));

    // create the extensions object and add it as an attribute
    Vector oids = new Vector();
    Vector values = new Vector();
    oids.add(X509Extensions.SubjectAlternativeName);
    values.add(new X509Extension(false, new DEROctetString(subjectAltName)));
    X509Extensions extensions = new X509Extensions(oids, values);
    Attribute attribute = new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new DERSet(extensions));

    return new PKCS10CertificationRequest(
           "SHA256withRSA",
           new X500Principal("CN=Requested Test Certificate"),
           pair.getPublic(),
           new DERSet(attribute),
           pair.getPrivate());
  }

  public static void main(String[] args) throws Exception {
    // create the keys
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "SC");
    kpGen.initialize(1024, Utils.createFixedRandom());
    KeyPair pair = kpGen.generateKeyPair();
    PKCS10CertificationRequest request = generateRequest(pair);
    PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
    pemWrt.writeObject(request);
    pemWrt.close();
  }
}

小さな Java プログラムは、次のように出力します。

-----BEGIN CERTIFICATE REQUEST-----
MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0
ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAm38mHcNo+YDhe1/XHRa1Cifj
EUwH6SQfqKQcY0sO4gGTVL/U5kBx/y0gIptrnGgUYgfwqptWoKHIqd4PGAuzHfwI
QrTfnYtLnN3dBdnOx/1mZuJ/fCD48H45sTVCcXbypxdwns2PZwgh1rt+jb7TJQii
5TteCLvzzb7FVb/Oc6MCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw
EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAJexpAYF6RvbYGiNS
kyaF1H8TpDOHaAuIvS4G2Kqw9xXJHYEDiNsQxMc4gWdx6ZNDzc1JYqFBaEV+c/zt
pRPLTRxTi841tLBUAzX7eFQ5EtLwJrKLlHCMXxg3DwcrPjRwidcE87Nl/sOyeT4K
btCXzqpLtklJi/giBl/4L+lQunU=
-----END CERTIFICATE REQUEST-----

問題は、その間 (この本は 2005 年のものです)、このクラスのほとんどが非推奨としてマークされていることです。証明書署名要求を作成する新しい方法は、Factory パターンを使用することです。

package chapter6;

import java.io.OutputStreamWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.util.Vector;

import org.spongycastle.asn1.DERPrintableString;
import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.spongycastle.asn1.x500.X500Name;
import org.spongycastle.asn1.x509.ExtendedKeyUsage;
import org.spongycastle.asn1.x509.KeyPurposeId;
import org.spongycastle.asn1.x509.KeyUsage;
import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
import org.spongycastle.asn1.x509.X509Extension;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openssl.PEMWriter;
import org.spongycastle.operator.ContentSigner;
import org.spongycastle.operator.ContentVerifierProvider;
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
import org.spongycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.spongycastle.pkcs.PKCS10CertificationRequest;
import org.spongycastle.pkcs.PKCS10CertificationRequestBuilder;

/**
 * Generation of a basic PKCS #10 request with an extension.
 */
public class PKCS10ExtensionExampleNew {
  static {
    BouncyCastleProvider prov = new org.spongycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(prov);
  }

  public static PKCS10CertificationRequest generateRequest(KeyPair pair) throws Exception {
    SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
    X500Name subject = new X500Name("CN=Requested Test Certificate");
    PKCS10CertificationRequestBuilder certificationRequestBuilder = new PKCS10CertificationRequestBuilder(subject, publicKeyInfo);

    certificationRequestBuilder.addAttribute(X509Extension.keyUsage, 
        new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment | KeyUsage.keyAgreement));

    Vector<KeyPurposeId> ekUsages = new Vector<KeyPurposeId>();
    ekUsages.add(KeyPurposeId.id_kp_clientAuth);
    ekUsages.add(KeyPurposeId.id_kp_serverAuth);
    certificationRequestBuilder.addAttribute(X509Extension.extendedKeyUsage, new ExtendedKeyUsage(ekUsages));

    JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA1WithRSAEncryption");
    contentSignerBuilder.setProvider("SC");
    ContentSigner contentSigner = contentSignerBuilder.build(pair.getPrivate());

    DERPrintableString password = new DERPrintableString("secret123");
    certificationRequestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_challengePassword, password);

    PKCS10CertificationRequest certificationRequest = certificationRequestBuilder.build(contentSigner);

    JcaContentVerifierProviderBuilder contentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
    ContentVerifierProvider contentVerifierProvider = contentVerifierProviderBuilder.build(pair.getPublic());
    System.out.println("isSignatureValid? " + certificationRequest.isSignatureValid(contentVerifierProvider));
    System.out.println(certificationRequest.getSubject());
    return certificationRequest;
  }

  public static void main(String[] args) throws Exception {
    // create the keys
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "SC");
    kpGen.initialize(1024, Utils.createFixedRandom());
    KeyPair pair = kpGen.generateKeyPair();
    PKCS10CertificationRequest request = generateRequest(pair);
    PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
    pemWrt.writeObject(request);
    pemWrt.close();
  }
}

PEM 生成で失敗するため、証明書要求は適切にビルドされません。

isSignatureValid? true
CN=Requested Test Certificate
Exception in thread "main" org.spongycastle.util.io.pem.PemGenerationException: unknown object passed - can't encode.
  at org.spongycastle.openssl.MiscPEMGenerator.createPemObject(MiscPEMGenerator.java:208)
  at org.spongycastle.openssl.MiscPEMGenerator.generate(MiscPEMGenerator.java:333)
  at org.spongycastle.util.io.pem.PemWriter.writeObject(PemWriter.java:76)
  at org.spongycastle.openssl.PEMWriter.writeObject(PEMWriter.java:45)
  at be.boeboe.spongycastle.chapter6.PKCS10ExtensionExampleNew.main(PKCS10ExtensionExampleNew.java:71)

リクエストを作成する 2 回目の試行が失敗した理由を知っている人はいますか? X509V3Certificate 証明書を古い方法と新しい方法の両方で作成しましたが、問題はありませんでしたが、これらの違いをここに示したものの隣に置いても、賢明にはなりませんでした。

どんな助けでも親切に感謝します。

ボボエ

4

0 に答える 0