生成并签名JSON Web Token时RSA要求PrivateKey报错如何解决
报错根本原因
- 你选择的
RS256属于非对称RSA签名算法,要求必须传入java.security.PrivateKey接口的实现类作为签名密钥。你当前代码中使用的SecretKeySpec是对称加密算法(如HS256系列)专用的密钥类,类型不匹配直接触发参数校验异常。 - 你传入的Base64内容是完整的PEM格式私钥,包含头尾标识
-----BEGIN RSA PRIVATE KEY-----、-----END RSA PRIVATE KEY-----以及换行符,不能直接解码后用于生成密钥对象,需要先清洗格式。
修复方案
你需要先将PEM格式的RSA私钥转换为Java标准的PrivateKey对象,再传入签名方法,完整修改后的代码如下:
import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Date; import io.jsonwebtoken.*; import javax.xml.bind.DatatypeConverter; public class JwtSignTest { public static void main(String[] args) throws Exception { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256; long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); // 1. 处理PEM格式私钥 String pemKey = "你自己的Base64编码的PEM私钥字符串"; // 先解码Base64得到PEM明文 String pemContent = new String(DatatypeConverter.parseBase64Binary(pemKey)); // 去除头尾标记和所有换行、空格 String privateKeyContent = pemContent .replace("-----BEGIN RSA PRIVATE KEY-----", "") .replace("-----END RSA PRIVATE KEY-----", "") .replaceAll("\\s+", ""); // 再次解码得到私钥二进制内容 byte[] keyBytes = DatatypeConverter.parseBase64Binary(privateKeyContent); // 2. 生成标准PrivateKey对象 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); PrivateKey privateKey = kf.generatePrivate(spec); // 3. 构造JWT,传入PrivateKey签名 JwtBuilder builder = Jwts.builder().setId("ID") .setIssuedAt(now) .setSubject("subject") .setIssuer("issuer") .signWith(signatureAlgorithm, privateKey); System.out.println("-------------------------------------"+builder.compact()); } }
兼容说明
如果执行时提示invalid key format,说明你的私钥是PKCS1格式,Java原生KeyFactory默认只支持PKCS8格式,可以做如下处理:
- 用openssl命令将PKCS1私钥转为PKCS8格式:
openssl pkcs8 -topk8 -inform PEM -in 你的私钥文件路径 -outform PEM -nocrypt,再提取转换后的Base64内容使用 - 也可以引入BouncyCastle加密库,直接解析PKCS1格式的RSA私钥
内容的提问来源于stack exchange,提问作者Ankit Dabhi
相关产品推荐
相关产品推荐

