You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java(BouncyCastle)中设置签名大小,生成2048公钥128字节签名证书?

问题描述

我正在用BouncyCastle生成证书文件,现有代码能正常运行,但无法控制签名长度。已知在SHA256WITHRSA算法下,2048位RSA密钥对应256字节签名,1024位对应128字节。我需要生成带有2048位公钥,但签名大小为128字节的DER格式证书。

现有代码示例

Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = createKeyPair();

JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
    new X500Name("CN=Issuer"), 
    BigInteger.ONE, 
    new GregorianCalendar().getTime(), 
    new GregorianCalendar().getTime(), 
    new X500Name("CN=Subject"), 
    keyPair.getPublic()
);
            
JcaContentSignerBuilder signerBuiler = new JcaContentSignerBuilder("SHA256WITHRSA")
    .setProvider(BouncyCastleProvider.PROVIDER_NAME);
ContentSigner contentSigner = signerBuiler.build(keyPair.getPrivate());
X509Certificate certificate = new JcaX509CertificateConverter()
    .setProvider(BouncyCastleProvider.PROVIDER_NAME)
    .getCertificate(certBuilder.build(contentSigner));

certificate.verify(keyPair.getPublic());
System.out.println(certificate);

目标效果

生成包含2048位RSA公钥、128字节签名段的DER格式证书,证书结构中签名长度固定为128字节,公钥段对应2048位密钥。

解决方案

要实现该需求,核心是分离签发密钥与主体公钥:用1024位RSA私钥生成128字节签名,同时将2048位RSA公钥作为证书的主体公钥嵌入。具体步骤如下:

  1. 生成两个RSA密钥对:
    • 1024位密钥对:用于签发证书,生成128字节签名
    • 2048位密钥对:作为证书的主体公钥
  2. 使用签发者的1024位私钥签名证书内容,证书的主体公钥使用2048位的公钥。

修改后的代码示例

Security.addProvider(new BouncyCastleProvider());

// 生成两个密钥对:签发用1024位,主体用2048位
KeyPair issuerKeyPair = createKeyPair(1024);
KeyPair subjectKeyPair = createKeyPair(2048);

// 构建证书,主体公钥采用2048位的密钥
JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
    new X500Name("CN=Issuer"), 
    BigInteger.ONE, 
    new GregorianCalendar().getTime(), 
    new GregorianCalendar().getTime(), 
    new X500Name("CN=Subject"), 
    subjectKeyPair.getPublic()
);

// 用签发者的1024位私钥生成SHA256WITHRSA签名(长度128字节)
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA256WITHRSA")
    .setProvider(BouncyCastleProvider.PROVIDER_NAME);
ContentSigner contentSigner = signerBuilder.build(issuerKeyPair.getPrivate());

// 生成并验证证书
X509Certificate certificate = new JcaX509CertificateConverter()
    .setProvider(BouncyCastleProvider.PROVIDER_NAME)
    .getCertificate(certBuilder.build(contentSigner));

// 验证需使用签发者的1024位公钥
certificate.verify(issuerKeyPair.getPublic());
System.out.println(certificate);

// 导出为DER格式证书文件
try (FileOutputStream fos = new FileOutputStream("custom_cert.der")) {
    fos.write(certificate.getEncoded());
} catch (IOException e) {
    e.printStackTrace();
}

补充说明

  • 上述代码中createKeyPair(int keySize)方法需支持指定密钥长度,示例实现如下:
private static KeyPair createKeyPair(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
    keyGen.initialize(keySize, new SecureRandom());
    return keyGen.generateKeyPair();
}
  • 标准RSA签名长度与私钥长度一致,因此只有用1024位私钥签名才能得到128字节的签名值;证书主体公钥可独立设置为2048位,二者无冲突。
  • 验证证书时必须使用签发者的1024位公钥,而非主体的2048位公钥。

内容的提问来源于stack exchange,提问作者Dong0321

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:25:50