如何在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公钥作为证书的主体公钥嵌入。具体步骤如下:
- 生成两个RSA密钥对:
- 1024位密钥对:用于签发证书,生成128字节签名
- 2048位密钥对:作为证书的主体公钥
- 使用签发者的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
相关产品推荐
相关产品推荐

