《Java加密工具与技术》8:X.509证书和属性证书
- 游戏开发
- 2025-09-13 00:00:01

X.500 可辨别名称
X.500 可辨别名称(Distinguished Name,简称DN),是用于在X.500目录服务中唯一标识一个条目(Entry)的名称。它由一系列相对可辨别名称(Relative Distinguished Names,简称RDNs)组成,每个RDN由一个或多个属性值对构成,这些属性值对在不同的目录级别上提供了条目的唯一标识。在X.500目录服务中,DN用于确保每个条目都可以被唯一地识别和访问。
例如,一个X.500 DN可能看起来像这样:
CN=John Doe,OU=Users,DC=example,DC=com在这个例子中:
CN=John Doe 是一个RDN,表示通用名称(Common Name)为“John Doe”。
OU=Users 是另一个RDN,表示组织单位(Organizational Unit)为“Users”。
DC=example 和 DC=com 是额外的RDNs,表示域组件(Domain Component)分别为“example”和“com”。
X.500 DN在多种应用中被使用,包括在公钥基础设施(PKI)中标识证书持有者,以及在轻量级目录访问协议(LDAP)中标识目录条目。
X500Principal 使用示例X500Principal 类用于表示X.500可辨别名称(Distinguished Name, DN)。它通常用于处理与安全相关的操作,例如在公钥基础设施(PKI)中处理X.509证书的主题或颁发者名称。
import javax.security.auth.x500.X500Principal; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.io.FileInputStream; public class X500PrincipalExample { public static void main(String[] args) { try { // 加载X.509证书 FileInputStream fis = new FileInputStream("path/to/your/certificate.crt"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(fis); fis.close(); // 获取证书的主题DN X500Principal subjectDN = cert.getSubjectX500Principal(); System.out.println("Subject DN: " + subjectDN.getName()); // 获取证书的颁发者DN X500Principal issuerDN = cert.getIssuerX500Principal(); System.out.println("Issuer DN: " + issuerDN.getName()); // 使用X500Principal的构造函数创建一个新的DN X500Principal newDN = new X500Principal("CN=John Doe, OU=Users, O=Example Corp, C=US"); System.out.println("New DN: " + newDN.getName()); } catch (Exception e) { e.printStackTrace(); } } } X500Name (BouncyCastle)使用示例X500Name 类是用于表示X.500可辨别名称(Distinguished Name, DN)的另一种方式。它通常用于处理与安全相关的操作,例如在公钥基础设施(PKI)中处理X.509证书的主题或颁发者名称。X500Name 类通常与BouncyCastle库一起使用,因为它是BouncyCastle库的一部分,而不是标准JDK的一部分。
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x500.style.IETFUtils; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.io.FileInputStream; public class X500NameExample { public static void main(String[] args) { try { // 加载X.509证书 FileInputStream fis = new FileInputStream("path/to/your/certificate.crt"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(fis); fis.close(); // 将X509Certificate转换为X500Name JcaX509CertificateHolder certHolder = new JcaX509CertificateHolder(cert); X500Name subjectDN = certHolder.getSubject(); X500Name issuerDN = certHolder.getIssuer(); // 输出主题DN System.out.println("Subject DN: " + subjectDN.toString()); // 输出颁发者DN System.out.println("Issuer DN: " + issuerDN.toString()); // 获取主题DN中的特定属性(例如通用名称CN) String commonName = IETFUtils.valueToString(subjectDN.getRDNs(BCStyle.CN)[0].getFirst().getValue()); System.out.println("Common Name (CN): " + commonName); // 创建一个新的X500Name X500Name newDN = new X500Name("CN=John Doe, OU=Users, O=Example Corp, C=US"); System.out.println("New DN: " + newDN.toString()); } catch (Exception e) { e.printStackTrace(); } } } X500NameBuilder 新建X500Name 示例X500NameBuilder 是BouncyCastle库提供的一个工具类,用于构建 X500Name 对象。X500NameBuilder 提供了一种灵活的方式来创建和自定义X.500可辨别名称(Distinguished Name, DN)。
使用 addRDN 方法添加相对可辨别名称(RDN)。
每个RDN由一个属性类型(如 BCStyle.CN)和一个属性值(如 "John Doe")组成。
常用的属性类型包括:
BCStyle.CN:通用名称(Common Name)
BCStyle.OU:组织单位(Organizational Unit)
BCStyle.O:组织名称(Organization)
BCStyle.L:地点(Locality)
BCStyle.ST:州/省(State or Province)
BCStyle.C:国家代码(Country Code)
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; public class X500NameBuilderExample { public static void main(String[] args) { // 创建X500NameBuilder实例 X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); // 添加属性到DN builder.addRDN(BCStyle.CN, "John Doe"); // 通用名称 (Common Name) builder.addRDN(BCStyle.OU, "Engineering"); // 组织单位 (Organizational Unit) builder.addRDN(BCStyle.O, "Example Corp"); // 组织名称 (Organization) builder.addRDN(BCStyle.L, "New York"); // 地点 (Locality) builder.addRDN(BCStyle.ST, "NY"); // 州/省 (State or Province) builder.addRDN(BCStyle.C, "US"); // 国家代码 (Country Code) // 构建X500Name对象 X500Name x500Name = builder.build(); // 输出X500Name System.out.println("X500Name: " + x500Name.toString()); } } X500NameBuilder 修改X500Name 示例 X500Name originalName = new X500Name("CN=Alice, OU=Development, O=Example Corp, C=US"); // 使用X500NameBuilder从现有名称构建 X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); for (var rdn : originalName.getRDNs()) { builder.addRDN(rdn.getFirst()); } // 添加新属性 builder.addRDN(BCStyle.OU, "Engineering"); // 构建新的X500Name X500Name newName = builder.build(); System.out.println("New X500Name: " + newName.toString()); 公钥证书 1. X509v1CertificateBuilder用途:用于构建X.509版本1(v1)证书。
特点:
X.509 v1 证书是最简单的证书格式,仅包含基本字段,如主题名称、颁发者名称、有效期和公钥。
不支持扩展:X.509 v1 证书没有扩展字段,因此无法添加自定义扩展(如密钥用途、扩展密钥用途等)。
使用场景:由于功能有限,X.509 v1 证书在现代应用中较少使用,通常用于简单的场景或兼容旧系统。
2. X509v2AttributeCertificateBuilder用途:用于构建X.509版本2(v2)属性证书。
特点:
属性证书(Attribute Certificate)与传统的公钥证书不同,它不包含公钥,而是包含与某个实体(通常是公钥证书的持有者)相关的属性信息。
属性证书通常用于基于角色的访问控制(RBAC)或其他与权限相关的场景。
支持扩展:X.509 v2 属性证书可以包含扩展字段。
3. X509v3CertificateBuilder用途:用于构建X.509版本3(v3)证书。
特点:
X.509 v3 证书是最常用的证书格式,支持扩展字段。
支持扩展:X.509 v3 证书可以包含各种扩展字段,如密钥用途(Key Usage)、扩展密钥用途(Extended Key Usage)、主题备用名称(Subject Alternative Name)等。
使用场景:X.509 v3 证书广泛应用于现代PKI(公钥基础设施)中,例如SSL/TLS证书、代码签名证书、客户端身份验证证书等。
创建一个基础的公钥证书 /** * Calculate a date in seconds (suitable for the PKIX profile - RFC 5280) * * @param hoursInFuture hours ahead of now, may be negative. * @return a Date set to now + (hoursInFuture * 60 * 60) seconds */ public static Date calculateDate(int hoursInFuture) { long secs = System.currentTimeMillis() / 1000; return new Date((secs + (hoursInFuture * 60 * 60)) * 1000); } private static long serialNumberBase = System.currentTimeMillis(); /** * Calculate a serial number using a monotonically increasing value. * * @return a BigInteger representing the next serial number in the sequence. */ public static synchronized BigInteger calculateSerialNumber() { return BigInteger.valueOf(serialNumberBase++); } /** * Build a sample self-signed V1 certificate to use as a trust anchor, or * root certificate. * * @param keyPair the key pair to use for signing and providing the * public key. * @param sigAlg the signature algorithm to sign the certificate with. * @return an X509CertificateHolder containing the V1 certificate. */ public static X509CertificateHolder createTrustAnchor( KeyPair keyPair, String sigAlg) throws OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo Root Certificate"); X500Name name = x500NameBld.build(); X509v1CertificateBuilder certBldr = new JcaX509v1CertificateBuilder( name, calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), name, keyPair.getPublic()); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(keyPair.getPrivate()); return certBldr.build(signer); }调用示例
public static X509KeyCertPair createTrustCert() throws GeneralSecurityException, OperatorCreationException { KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair trustKp = kpGen.generateKeyPair(); X509CertificateHolder trustCert = createTrustAnchor(trustKp, "SHA256withECDSA"); return new X509KeyCertPair(trustKp, trustCert); } 转换X509CertificateHolder为X509Certificate /** * Simple method to convert an X509CertificateHolder to an X509Certificate * using the java.security.cert.CertificateFactory class. */ public static X509Certificate convertX509CertificateHolder( X509CertificateHolder certHolder) throws GeneralSecurityException, IOException { CertificateFactory cFact = CertificateFactory.getInstance("X.509", "BC"); return (X509Certificate)cFact.generateCertificate( new ByteArrayInputStream( certHolder.getEncoded())); } 创建带有扩展的CA证书 /** * Build a sample V3 intermediate certificate that can be used as a CA * certificate. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @param followingCACerts * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createIntermediateCertificate( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey, int followingCACerts) throws CertIOException, GeneralSecurityException, OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo Intermediate Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(followingCACerts)) .addExtension(Extension.keyUsage, true, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); }调用示例
public static X509KeyCertPair createInterCert(X509KeyCertPair trustPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey trustAnchorKey = trustPair.getKeyPair().getPrivate(); X509CertificateHolder trustCert = trustPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair caKp = kpGen.generateKeyPair(); X509CertificateHolder caCert = createIntermediateCertificate(trustCert, trustAnchorKey, "SHA256withECDSA", caKp.getPublic(), 0); return new X509KeyCertPair(caKp, caCert); } 创建终端实体证书 /** * Create a general end-entity certificate for use in verifying digital * signatures. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createEndEntity( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey) throws CertIOException, GeneralSecurityException, OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo End-Entity Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); }调用示例
public static X509KeyCertPair createEECert(X509KeyCertPair caPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey caPrivKey = caPair.getKeyPair().getPrivate(); X509CertificateHolder caCert = caPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair eeKp = kpGen.generateKeyPair(); X509CertificateHolder eeCert = createEndEntity(caCert, caPrivKey, "SHA256withECDSA", eeKp.getPublic()); return new X509KeyCertPair(eeKp, eeCert); } 使用ExtendedKeyUsage /** * Create a special purpose end entity cert which is associated with a * particular key purpose. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @param keyPurpose the specific KeyPurposeId to associate with this * certificate's public key. * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createSpecialPurposeEndEntity( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey, KeyPurposeId keyPurpose) throws OperatorCreationException, CertIOException, GeneralSecurityException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo End-Entity Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) .addExtension(Extension.extendedKeyUsage, true, new ExtendedKeyUsage(keyPurpose)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); }调用示例
public static X509KeyCertPair createEESpecCert(X509KeyCertPair caPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey caPrivKey = caPair.getKeyPair().getPrivate(); X509CertificateHolder caCert = caPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair specEEKp = kpGen.generateKeyPair(); X509CertificateHolder specEECert = createSpecialPurposeEndEntity(caCert, caPrivKey, "SHA256withECDSA", specEEKp.getPublic(), KeyPurposeId.id_kp_timeStamping); return new X509KeyCertPair(specEEKp, specEECert); } 属性证书 public static X509AttributeCertificateHolder createAttributeCertificate( X509CertificateHolder issuerCert, PrivateKey issuerKey, String sigAlg, X509CertificateHolder holderCert, String holderRoleUri) throws OperatorCreationException { X509v2AttributeCertificateBuilder acBldr = new X509v2AttributeCertificateBuilder( new AttributeCertificateHolder(holderCert), new AttributeCertificateIssuer(issuerCert.getSubject()), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 7)); GeneralName roleName = new GeneralName( GeneralName.uniformResourceIdentifier, holderRoleUri); acBldr.addAttribute( X509AttributeIdentifiers.id_at_role, new RoleSyntax(roleName)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(issuerKey); return acBldr.build(signer); }调用示例
public static X509AttributeCertificateHolder createAttrCertSample(PrivateKey issuerSigningKey, X509CertificateHolder issuerCert, X509CertificateHolder holderCert) throws OperatorCreationException { X509AttributeCertificateHolder attrCert = createAttributeCertificate(issuerCert, issuerSigningKey, "SHA256withECDSA", holderCert, "id://DAU123456789"); return attrCert; } 附录(完整代码) package chapter8; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x500.style.RFC4519Style; import org.bouncycastle.asn1.x509.*; import org.bouncycastle.cert.*; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.*; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Date; /** * Example methods showing generation and verification of X.509 certificates */ public class JcaX509Certificate { /** * Calculate a date in seconds (suitable for the PKIX profile - RFC 5280) * * @param hoursInFuture hours ahead of now, may be negative. * @return a Date set to now + (hoursInFuture * 60 * 60) seconds */ public static Date calculateDate(int hoursInFuture) { long secs = System.currentTimeMillis() / 1000; return new Date((secs + (hoursInFuture * 60 * 60)) * 1000); } private static long serialNumberBase = System.currentTimeMillis(); /** * Calculate a serial number using a monotonically increasing value. * * @return a BigInteger representing the next serial number in the sequence. */ public static synchronized BigInteger calculateSerialNumber() { return BigInteger.valueOf(serialNumberBase++); } /** * Simple method to convert an X509CertificateHolder to an X509Certificate * using the java.security.cert.CertificateFactory class. */ public static X509Certificate convertX509CertificateHolder( X509CertificateHolder certHolder) throws GeneralSecurityException, IOException { CertificateFactory cFact = CertificateFactory.getInstance("X.509", "BC"); return (X509Certificate)cFact.generateCertificate( new ByteArrayInputStream( certHolder.getEncoded())); } /** * Convert an X500Name to use the IETF style. */ public static X500Name toIETFName(X500Name name) { return X500Name.getInstance(RFC4519Style.INSTANCE, name); } public static X509KeyCertPair createTrustCert() throws GeneralSecurityException, OperatorCreationException { KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair trustKp = kpGen.generateKeyPair(); X509CertificateHolder trustCert = createTrustAnchor(trustKp, "SHA256withECDSA"); return new X509KeyCertPair(trustKp, trustCert); } /** * Build a sample self-signed V1 certificate to use as a trust anchor, or * root certificate. * * @param keyPair the key pair to use for signing and providing the * public key. * @param sigAlg the signature algorithm to sign the certificate with. * @return an X509CertificateHolder containing the V1 certificate. */ public static X509CertificateHolder createTrustAnchor( KeyPair keyPair, String sigAlg) throws OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo Root Certificate"); X500Name name = x500NameBld.build(); X509v1CertificateBuilder certBldr = new JcaX509v1CertificateBuilder( name, calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), name, keyPair.getPublic()); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(keyPair.getPrivate()); return certBldr.build(signer); } public static X509KeyCertPair createInterCert(X509KeyCertPair trustPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey trustAnchorKey = trustPair.getKeyPair().getPrivate(); X509CertificateHolder trustCert = trustPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair caKp = kpGen.generateKeyPair(); X509CertificateHolder caCert = createIntermediateCertificate(trustCert, trustAnchorKey, "SHA256withECDSA", caKp.getPublic(), 0); return new X509KeyCertPair(caKp, caCert); } /** * Build a sample V3 intermediate certificate that can be used as a CA * certificate. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @param followingCACerts * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createIntermediateCertificate( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey, int followingCACerts) throws CertIOException, GeneralSecurityException, OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo Intermediate Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(followingCACerts)) .addExtension(Extension.keyUsage, true, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); } public static X509KeyCertPair createEECert(X509KeyCertPair caPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey caPrivKey = caPair.getKeyPair().getPrivate(); X509CertificateHolder caCert = caPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair eeKp = kpGen.generateKeyPair(); X509CertificateHolder eeCert = createEndEntity(caCert, caPrivKey, "SHA256withECDSA", eeKp.getPublic()); return new X509KeyCertPair(eeKp, eeCert); } /** * Create a general end-entity certificate for use in verifying digital * signatures. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createEndEntity( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey) throws CertIOException, GeneralSecurityException, OperatorCreationException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo End-Entity Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); } public static X509KeyCertPair createEESpecCert(X509KeyCertPair caPair) throws GeneralSecurityException, OperatorCreationException, CertIOException { PrivateKey caPrivKey = caPair.getKeyPair().getPrivate(); X509CertificateHolder caCert = caPair.getCert(); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC"); KeyPair specEEKp = kpGen.generateKeyPair(); X509CertificateHolder specEECert = createSpecialPurposeEndEntity(caCert, caPrivKey, "SHA256withECDSA", specEEKp.getPublic(), KeyPurposeId.id_kp_timeStamping); return new X509KeyCertPair(specEEKp, specEECert); } /** * Create a special purpose end entity cert which is associated with a * particular key purpose. * * @param signerCert certificate carrying the public key that will later * be used to verify this certificate's signature. * @param signerKey private key used to generate the signature in the * certificate. * @param sigAlg the signature algorithm to sign the certificate with. * @param certKey public key to be installed in the certificate. * @param keyPurpose the specific KeyPurposeId to associate with this * certificate's public key. * @return an X509CertificateHolder containing the V3 certificate. */ public static X509CertificateHolder createSpecialPurposeEndEntity( X509CertificateHolder signerCert, PrivateKey signerKey, String sigAlg, PublicKey certKey, KeyPurposeId keyPurpose) throws OperatorCreationException, CertIOException, GeneralSecurityException { X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE) .addRDN(BCStyle.C, "AU") .addRDN(BCStyle.ST, "Victoria") .addRDN(BCStyle.L, "Melbourne") .addRDN(BCStyle.O, "The Legion of the Bouncy Castle") .addRDN(BCStyle.CN, "Demo End-Entity Certificate"); X500Name subject = x500NameBld.build(); X509v3CertificateBuilder certBldr = new JcaX509v3CertificateBuilder( signerCert.getSubject(), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 31), subject, certKey); JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBldr.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(signerCert)) .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certKey)) .addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) .addExtension(Extension.extendedKeyUsage, true, new ExtendedKeyUsage(keyPurpose)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(signerKey); return certBldr.build(signer); } /** * Extract the DER encoded value octets of an extension from a JCA * X509Certificate. * * @param cert the certificate of interest. * @param extensionOID the OID associated with the extension of interest. * @return the DER encoding inside the extension, null if extension missing. */ public static byte[] extractExtensionValue( X509Certificate cert, ASN1ObjectIdentifier extensionOID) { byte[] octString = cert.getExtensionValue(extensionOID.getId()); if (octString == null) { return null; } return ASN1OctetString.getInstance(octString).getOctets(); } public static X509AttributeCertificateHolder createAttrCertSample(PrivateKey issuerSigningKey, X509CertificateHolder issuerCert, X509CertificateHolder holderCert) throws OperatorCreationException { X509AttributeCertificateHolder attrCert = createAttributeCertificate(issuerCert, issuerSigningKey, "SHA256withECDSA", holderCert, "id://DAU123456789"); return attrCert; } public static X509AttributeCertificateHolder createAttributeCertificate( X509CertificateHolder issuerCert, PrivateKey issuerKey, String sigAlg, X509CertificateHolder holderCert, String holderRoleUri) throws OperatorCreationException { X509v2AttributeCertificateBuilder acBldr = new X509v2AttributeCertificateBuilder( new AttributeCertificateHolder(holderCert), new AttributeCertificateIssuer(issuerCert.getSubject()), calculateSerialNumber(), calculateDate(0), calculateDate(24 * 7)); GeneralName roleName = new GeneralName( GeneralName.uniformResourceIdentifier, holderRoleUri); acBldr.addAttribute( X509AttributeIdentifiers.id_at_role, new RoleSyntax(roleName)); ContentSigner signer = new JcaContentSignerBuilder(sigAlg) .setProvider("BC").build(issuerKey); return acBldr.build(signer); } }《Java加密工具与技术》8:X.509证书和属性证书由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“《Java加密工具与技术》8:X.509证书和属性证书”