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 証明書を古い方法と新しい方法の両方で作成しましたが、問題はありませんでしたが、これらの違いをここに示したものの隣に置いても、賢明にはなりませんでした。
どんな助けでも親切に感謝します。
ボボエ