使用Java的private键创建一个RSA256 JWT
我正在尝试为行API创建访问令牌 以下是我的私钥
{
“ alg”:“ rs256”,
“ D”:“ TC4IJ ...... WQSQIQ”,
“ dp”:“ njg12kiro ... nc02gdk-d8”,
“ dq”:“ uzrtj ..... ha70”,
“ e”:“ aqab”,
“ ext”:true,
“ key_ops”:[
“标志”
],
“ kty”:“ rsa”,
“ n”:“ rj_fxz ..... kundvoohimw”,
“ p”:“ 70K5HA_WTNMAEM ..... Z4PG79DZ5U”,
“ Qi”:“ 7J7GZQQ .... NFS7B8HRIC4”
}
下面的代码来创建带有有效载荷和标头的密钥的令牌
String token = null;
byte[] privateKey = ResourceUtil.readStr("line_key/privatekey-dev.json", StandardCharsets.UTF_8).getBytes();
// ペイロードの設定
Map<String, Object> payloadClaims = new HashMap<>();
// line channel id
payloadClaims.put("iss", "XXXXXXX");
payloadClaims.put("sub", "XXXXXXX");
payloadClaims.put("aud", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
payloadClaims.put("exp", new Date(System.currentTimeMillis() + 60 * 30));
payloadClaims.put("token_exp", 60 * 60 * 24 * 30);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKey);
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
//Algorithm algorithm = Algorithm.RSA256(null, privKey);
token = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "RS256")
.setHeaderParam("kid", "XXXXXXX").setClaims(payloadClaims)
.signWith(SignatureAlgorithm.RS256, privKey)
.compact();
} catch (Exception e) {
log.error(e.getMessage());
}
我想使用 但是它总是显示
java.security.spec.invalidkeyspecexception:java.security.invalidkeyexception:无效的密钥格式
即使我使用base64来解码从JSON文件中读取的私钥,也无法使用。
byte[] keyContentAsBytes = Base64.getMimeDecoder().decode(privateKey);
任何身体都可以告诉我如何解决这个问题。
谢谢
PS:JWT可以由Python与
生成
key = RSAAlgorithm.from_jwk(privateKey)
JWT = jwt.encode(payload, key, algorithm="RS256", headers=headers, json_encoder=None)
I am trying to create an access token for line API
below is my private key
{
"alg": "RS256",
"d": "TC4Ij......wqSQIQ",
"dp": "nJg12KiRo...nc02GdK-d8",
"dq": "UzRtJ.....HA70",
"e": "AQAB",
"ext": true,
"key_ops": [
"sign"
],
"kty": "RSA",
"n": "rj_fXZ.....kuNDvOOHimw",
"p": "70k5HA_wTnmAEm.....z4pG79DZ5U",
"qi": "7j7gzQq....NfS7B8HRiC4"
}
I wanted to create a token by the the key with payload and header using the code below
String token = null;
byte[] privateKey = ResourceUtil.readStr("line_key/privatekey-dev.json", StandardCharsets.UTF_8).getBytes();
// ペイロードの設定
Map<String, Object> payloadClaims = new HashMap<>();
// line channel id
payloadClaims.put("iss", "XXXXXXX");
payloadClaims.put("sub", "XXXXXXX");
payloadClaims.put("aud", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
payloadClaims.put("exp", new Date(System.currentTimeMillis() + 60 * 30));
payloadClaims.put("token_exp", 60 * 60 * 24 * 30);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKey);
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
//Algorithm algorithm = Algorithm.RSA256(null, privKey);
token = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "RS256")
.setHeaderParam("kid", "XXXXXXX").setClaims(payloadClaims)
.signWith(SignatureAlgorithm.RS256, privKey)
.compact();
} catch (Exception e) {
log.error(e.getMessage());
}
Since the private the not encoded so I didnt use Base64 to decode it.
But it always showed
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
Even if I use Base64 to decode the private key read from the json file it didnt work.
byte[] keyContentAsBytes = Base64.getMimeDecoder().decode(privateKey);
Can any body tell me how to solve this issue.
Thanks
PS: jwt can be generated by python with
key = RSAAlgorithm.from_jwk(privateKey)
JWT = jwt.encode(payload, key, algorithm="RS256", headers=headers, json_encoder=None)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,由于您正在重新发明日期算术轮,因此您的令牌只能有效1.8秒。我怀疑这就是您的意图。从
Java.Time
中使用更高的API,而不是魔术数字,并从java.util
中使用过时的类型,以便您的代码明确表示意图。您没有PKCS-#8编码的密钥规范,因此您不能使用
pkcs8encodedkeyspec
。由于某种原因,我无法理解,JWK忽略了像PKC#8这样的现有标准,并发明了一种新格式,具有肿但仍然不透明的JSON编码。如果您确实需要自己转换私钥,则可以从JWK获取参数,并创建
rsaprivatecrtkeyspec
。我说的是“真的,我会感到惊讶从JWK表示形式加载privateKey
。这是JWK RSA私有密钥成员和Java的
rsaprivatecrtkeyspec
属性之间的映射。base-64解释JWK中的每个值正面:
新的BigInteger(+1,大小)
。实例化arsaprivatecrtkeyspec
,并将其与您的key -factory
代替pcks8encodedkeyspec
。First, because you are re-inventing the date-arithmetic wheel, your token will only be valid for 1.8 seconds. I doubt that's what you intended. Use higher level APIs from
java.time
instead of magic numbers and obsolete types fromjava.util
so that your code states the intent clearly.You don't have a PKCS-#8–encoded key spec, so you can't use
PKCS8EncodedKeySpec
. For some reason I can't fathom, JWK ignored existing standards like PKCS #8 and invented a new format with a bloated yet still opaque JSON encoding.If you really need to convert the private key yourself, you can get the parameters from the JWK and create a
RSAPrivateCrtKeySpec
. I say "really," because I'd be surprised if the library you are using doesn't have some means to load aPrivateKey
from a JWK representation.Here is the mapping between JWK RSA private key members and Java's
RSAPrivateCrtKeySpec
properties.Base-64 decode each value in the JWK, then create a
BigInteger
with the resulting magnitude, specifying the sign is positive:new BigInteger(+1, magnitude)
. Instantiate aRSAPrivateCrtKeySpec
and use that with yourKeyFactory
in place of thePCKS8EncodedKeySpec
.