我目前正在使用bouncy castle创建一个PKCS10请求,其中包含一个主题:
X500Principal subject = new X500Principal("CN=foo.bar.com");
PKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(
subject, publicKey);
我现在需要为PKCS10请求添加主题替代。我一直无法弄清楚如何做到这一点。有什么建议吗?
解决方案:
根据第二个答案中提供的精彩信息,我能够弄清楚这一点。在下面的工作代码中,XName是一个包含主题名称和名称类型(DNS,RFC822等)的简单类。
String signerAlgo = "SHA256withRSA";
ContentSigner signGen = new JcaContentSignerBuilder(signerAlgo).build(privateKey);
X500Principal subject = new X500Principal(csr.getSubjectAsX500NameString());
PKCS10CertificationRequestBuilder builder =
new JcaPKCS10CertificationRequestBuilder(subject, publicKey);
/*
* Add SubjectAlternativeNames (SANs)
*/
if (csr.getSubjectAlternatives() != null && csr.getSubjectAlternatives().size() > 0) {
List<GeneralName> namesList = new ArrayList<>();
for (XName subjectAlt : csr.getSubjectAlternatives()) {
log.debug(m, d+2, "Adding SubjectAltName: %s", subjectAlt);
namesList.add(GeneralNameTool.toGeneralName(subjectAlt));
}
/*
* Use ExtensionsGenerator to add individual extensions.
*/
ExtensionsGenerator extGen = new ExtensionsGenerator();
GeneralNames subjectAltNames = new GeneralNames(namesList.toArray(new GeneralName [] {}));
extGen.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate());
}
PKCS10CertificationRequest request = builder.build(signGen);
StringWriter writer = new StringWriter();
JcaPEMWriter pem = new JcaPEMWriter(writer);
pem.writeObject(request);
pem.close();
答案 0 :(得分:2)
Mike遇到了同样的问题,我认为你的问题与尝试使用JcaPKCS10CertificationRequestBuilder(来自版本2 API)而不是使用已弃用的V1 API有关。
如果您访问BC维基页面并查找"X.509 Public Key Certificate and Certificate request generation",则可以合理地描述如何处理第1版API,这与David的Wrox书籍第212页上的列表非常相似Hook,&#34;用Java开始加密&#34;。
在描述如何创建CSR时,关于版本2 API的Wiki的文档非常糟糕。
总结一下如何使用v2 API,这里有一些基于V2测试用例的代码(要查找的类在此代码清单下面):
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
...
X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE);
// See e.g. http://javadox.com/org.bouncycastle/\
// bcprov-jdk15on/1.51/org/bouncycastle/asn1/x500/style/BCStyle.html
// for a description of the available RDNs
x500NameBld.addRDN(BCStyle.CN, commonName);
x500NameBld.addRDN(BCStyle.OU, orgCode);
x500NameBld.addRDN(BCStyle.UNIQUE_IDENTIFIER, "64 bit EUID goes here");
X500Name subject = x500NameBld.build();
/**
* My application needs to set the Key Usage section of the CSR
* (which for my app has a Criticality of "true" and a value of
* "digital signature" or "key agreement").
*/
Extension[] extSigning = new Extension[] {
new Extension(Extension.basicConstraints, true,
new DEROctetString(new BasicConstraints(true))),
new Extension(Extension.keyUsage, true,
new DEROctetString(new KeyUsage(KeyUsage.keyCertSign))),
};
Extension[] extKeyAgreement = new Extension[] {
new Extension(Extension.basicConstraints, true,
new DEROctetString(new BasicConstraints(true))),
new Extension(Extension.keyUsage, true,
new DEROctetString(new KeyUsage(KeyUsage.keyCertSign))),
};
PKCS10CertificationRequest req =
new JcaPKCS10CertificationRequestBuilder(
subject,
pair.getPublic())
.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,
new Extensions(isKaFlag==true?extKeyAgreement:extSigning))
.build(new JcaContentSignerBuilder("SHA256withECDSA")
.setProvider(BC)
.build(pair.getPrivate()));
return req; // The PKCS10 certificate signing request
我建议仔细查看专门针对v2 API的维基页面。
重要的是,一旦你找到了V2的 cert.test.PKCS10Test 的源代码,一切都开始有意义了。最后,我使用this JavaScript hex dumper for ASN1 检查它是否正确出来。