对接IRS API:如何在JWK输出中添加x5t与x5c参数
为RSA JWK添加x5t和x5c参数(NimbusDS实现)
要满足IRS的要求添加x5t和x5c参数,你需要将RSA密钥与X.509证书关联:
x5t:证书的SHA-1指纹(Base64URL编码)x5c:X.509证书链的Base64编码(DER格式,去除PEM头尾)
以下是修改后的代码,包含证书生成与JWK构建的完整流程:
依赖补充(如需生成自签名证书)
如果用BouncyCastle简化证书生成,添加Maven依赖:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>9.31</version> </dependency>
完整代码实现
package com.propfinancing.jwk; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; import com.nimbusds.jose.util.X509CertificateChain; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; import java.security.KeyPair; import java.security.Security; import java.security.cert.X509Certificate; import java.util.Date; import java.util.UUID; import java.math.BigInteger; import java.security.SecureRandom; public class GenerateKey { static { // 注册BouncyCastle安全提供者 Security.addProvider(new BouncyCastleProvider()); } // 生成自签名X.509证书(正式环境请使用IRS认可的CA签发证书) private static X509Certificate generateSelfSignedCert(KeyPair keyPair) throws Exception { X500Name issuer = new X500Name("CN=IRS API Client, OU=Finance, O=PropFinancing, L=New York, ST=NY, C=US"); X500Name subject = issuer; // 自签名证书,签发者与主体一致 Date startDate = new Date(); Date endDate = new Date(startDate.getTime() + 365L * 24 * 60 * 60 * 1000); // 有效期1年 // 构建签名器 ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption") .setProvider("BC") .build(keyPair.getPrivate()); // 构建证书 X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( issuer, new BigInteger(64, new SecureRandom()), startDate, endDate, subject, keyPair.getPublic() ); // 添加证书扩展 JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); certBuilder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(keyPair.getPublic())); certBuilder.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(keyPair.getPublic())); certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(true)); // 生成并返回证书 return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certBuilder.build(contentSigner)); } public static void main(String[] args) throws Exception { // 生成RSA密钥对 RSAKey rsaKey = new RSAKeyGenerator(2048) .keyUse(KeyUse.SIGNATURE) .keyID(UUID.randomUUID().toString()) .generate(); KeyPair keyPair = rsaKey.toKeyPair(); // 生成自签名证书 X509Certificate cert = generateSelfSignedCert(keyPair); // 构建包含x5t和x5c的JWK RSAKey jwkWithCert = new RSAKey.Builder(rsaKey) // 设置x5c:证书链(单证书时为单元素数组) .x509CertChain(new X509CertificateChain(cert)) // 自动计算并设置x5t:证书SHA-1指纹的Base64URL编码 .x509CertSHA1Thumbprint(rsaKey.computeX509CertSHA1Thumbprint(cert)) .build(); // 输出完整JWK(含私钥、x5t、x5c) System.out.println(jwkWithCert); // 输出公钥JWK(含x5t、x5c,用于提交给IRS) System.out.println(jwkWithCert.toPublicJWK()); } }
关键说明
- x5c参数:通过
x509CertChain方法传入证书链,NimbusDS会自动将证书DER编码为Base64字符串,填充到x5c字段中。 - x5t参数:调用
computeX509CertSHA1Thumbprint方法自动计算证书的SHA-1指纹并编码为Base64URL格式,无需手动计算。 - 正式环境注意:对接IRS时必须使用IRS认可的CA签发的证书,自签名证书仅用于测试。
内容的提问来源于stack exchange,提问作者Neil
相关产品推荐
相关产品推荐

