当前位置: 首页 > 知识库问答 >
问题:

在Java与充气城堡签署X509证书

白子明
2023-03-14

我需要用Java中的Bouncy Castle创建一个自签名X509证书,但我尝试包含的每个类都不推荐使用。我该怎么解决这个问题?还有其他课程吗?谢谢

共有3个答案

佴德曜
2023-03-14

这里有一个完整的自签名ECDSA证书生成器,它可以在客户端和服务器端的TLS连接中创建可用的证书。用BouncyCastle 1.57测试。类似的代码可用于创建RSA证书。

SecureRandom random = new SecureRandom();

// create keypair
KeyPairGenerator keypairGen = KeyPairGenerator.getInstance("EC");
keypairGen.initialize(256, random);
KeyPair keypair = keypairGen.generateKeyPair();

// fill in certificate fields
X500Name subject = new X500NameBuilder(BCStyle.INSTANCE)
    .addRDN(BCStyle.CN, "stackoverflow.com")
    .build();
byte[] id = new byte[20];
random.nextBytes(id);
BigInteger serial = new BigInteger(160, random);
X509v3CertificateBuilder certificate = new JcaX509v3CertificateBuilder(
    subject,
    serial,
    Date.from(LocalDate.of(2000, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()),
    Date.from(LocalDate.of(2035, 1, 1).atStartOfDay(ZoneOffset.UTC).toInstant()),
    subject,
    keypair.getPublic());
certificate.addExtension(Extension.subjectKeyIdentifier, false, id);
certificate.addExtension(Extension.authorityKeyIdentifier, false, id);
BasicConstraints constraints = new BasicConstraints(true);
certificate.addExtension(
    Extension.basicConstraints,
    true,
    constraints.getEncoded());
KeyUsage usage = new KeyUsage(KeyUsage.keyCertSign | KeyUsage.digitalSignature);
certificate.addExtension(Extension.keyUsage, false, usage.getEncoded());
ExtendedKeyUsage usageEx = new ExtendedKeyUsage(new KeyPurposeId[] {
    KeyPurposeId.id_kp_serverAuth,
    KeyPurposeId.id_kp_clientAuth
});
certificate.addExtension(
    Extension.extendedKeyUsage,
    false,
    usageEx.getEncoded());

// build BouncyCastle certificate
ContentSigner signer = new JcaContentSignerBuilder("SHA256withECDSA")
    .build(keypair.getPrivate());
X509CertificateHolder holder = certificate.build(signer);

// convert to JRE certificate
JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
converter.setProvider(new BouncyCastleProvider());
X509Certificate x509 = converter.getCertificate(holder);

// serialize in DER format
byte[] serialized = x509.getEncoded();
秋飞鸾
2023-03-14

注意:这个答案使用了包含11个简历的旧版本库。

以下是我使用的内容(BouncyCastle v1.38版):

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.util.Date;

import javax.security.auth.x500.X500Principal;

import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;

public class BouncyCastle {

    public static void main(String[] args) throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException {
        X509Certificate selfSignedX509Certificate = new BouncyCastle().generateSelfSignedX509Certificate();
        System.out.println(selfSignedX509Certificate);
    }

    public X509Certificate generateSelfSignedX509Certificate() throws CertificateEncodingException, InvalidKeyException, IllegalStateException,
            NoSuchProviderException, NoSuchAlgorithmException, SignatureException {
        addBouncyCastleAsSecurityProvider();

        // generate a key pair
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        keyPairGenerator.initialize(4096, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // build a certificate generator
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        X500Principal dnName = new X500Principal("cn=example");

        // add some options
        certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        certGen.setSubjectDN(new X509Name("dc=name"));
        certGen.setIssuerDN(dnName); // use the same
        // yesterday
        certGen.setNotBefore(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000));
        // in 2 years
        certGen.setNotAfter(new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000));
        certGen.setPublicKey(keyPair.getPublic());
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true,
                new ExtendedKeyUsage(KeyPurposeId.id_kp_timeStamping));

        // finally, sign the certificate with the private key of the same KeyPair
        X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");
        return cert;
    }

    public void addBouncyCastleAsSecurityProvider() {
        Security.addProvider(new BouncyCastleProvider());
    }
}

对于certGen。生成(keyPair.getPrivate(),“BC”) 要工作,必须添加BouncyCastle作为安全提供商。

我确认它可以与这个maven依赖项一起工作:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk16</artifactId>
    <version>1.38</version>
</dependency>

严子默
2023-03-14

更新到@Bewusstsein的答案。bouncyCastle类在截至本答案(5/11/2017)的最新版本中不建议使用。如果您使用的是1.55或更高版本:

public static Certificate selfSign(KeyPair keyPair, String subjectDN) throws OperatorCreationException, CertificateException, IOException
{
    Provider bcProvider = new BouncyCastleProvider();
    Security.addProvider(bcProvider);

    long now = System.currentTimeMillis();
    Date startDate = new Date(now);

    X500Name dnName = new X500Name(subjectDN);
    BigInteger certSerialNumber = new BigInteger(Long.toString(now)); // <-- Using the current timestamp as the certificate serial number

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(startDate);
    calendar.add(Calendar.YEAR, 1); // <-- 1 Yr validity

    Date endDate = calendar.getTime();

    String signatureAlgorithm = "SHA256WithRSA"; // <-- Use appropriate signature algorithm based on your keyPair algorithm.

    ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate());

    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, startDate, endDate, dnName, keyPair.getPublic());

    // Extensions --------------------------

    // Basic Constraints
    BasicConstraints basicConstraints = new BasicConstraints(true); // <-- true for CA, false for EndEntity

    certBuilder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, basicConstraints); // Basic Constraints is usually marked as critical.

    // -------------------------------------

    return new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(contentSigner));
}
 类似资料:
  • 我的项目正在对来自某些第三方软件的某些数据集进行签名验证。使用的签名算法是 。当我使用SDK附带的标准SUN加密提供程序时,一切都很顺利。最近我切换到了Bouncy Castle 1.50,之后,一些以前(即SUN提供者)进行验证的数据集开始失败,而其余的仍然被验证正常。 我探索了两个提供程序的源代码,结果发现SDK的默认提供程序对格式错误的签名有某种保护(同时能够恢复),而Bouncy Cast

  • 有人能解释一下为什么这段代码在解密密钥时会在最后一行抛出吗? 以下是来自https://stackoverflow.com/a/27886397/66722对于使用OAEP的RSA也是如此? “RSA/ECB/PKCS1Padding”实际上没有实现ECB模式加密。它应该被称为“RSA/None/PKCS1Padding”,因为它只能用于加密单个明文块(或者实际上是一个密钥)。这只是Sun/Ora

  • 我正在开发一个功能来对某些内容进行数字签名。我有一个带有私钥的有效证书。如何使用私钥和充气城堡进行数字签名? 我尝试了以下方法,但想要一些正确的方法来实现同样的使用充气城堡: 谢谢!

  • 我正在尝试使用.NET(CNG提供商)的现有ECDSA密钥,以便使用Bouncy Castle对数据进行签名,然后在两种签名格式(P1363和ASN.1)之间进行转换。然而,我总是得到不同的签名。我不太确定转换是否不正确,或者我是否使用了不正确的方法来使用Bouncy Castle读取.NET密钥。 由于某些原因,和已经不同,我假设问题甚至可能在转换之前就出现了。我已经看过许多StackOverf

  • 我在玩加密。我被困在用BouncyCastle加载密钥上。密钥是由PuTTYgen(SSH-2 RSA 4096位)生成的。也许有其他方法可以加载它吗? 我得到: “System.IO”类型的未处理异常。BouncyCastle.Crypto中出现“IOException”。dll<br>其他信息:意外的内容结束标记“” 已添加:我使用“ssh-keygen -t rsa -b 4096”生成了一

  • 问题内容: 任何人都可以向我展示(或提供指向)如何使用充气城堡在Java中加密文件的示例吗?我查看了bouncycastle.org,但找不到其API的任何文档。即使只是知道要使用哪些类,也对我入门很有帮助! 问题答案: 您要执行哪种类型的加密?基于密码(PBE),对称,不对称?这就是您配置Cipher的全部方法。 您不必使用任何BouncyCastle特定的API,只需使用它提供的算法即可。这是