java - 无法使用配置的 PublicKey 验证 RSA 签名。签名长度不正确:得到 255 但预期为 256
问题描述
我正在尝试学习如何使用RSA
公私钥对来签署 JWT。
我使用openssl
.
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
我正在设置环境变量如下
export PRIVATE_KEY_DEMO=`cat private_key.pem`
export PUBLIC_KEY_DEMO=`cat public_key.pem`
我有以下创建PrivateKey
和PublicKey
public PrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, URISyntaxException {
String key = env.getProperty("PRIVATE_KEY_DEMO");
key = key.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replace("\n", "");
byte[] keyBytes = Base64.getMimeDecoder().decode(key);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
private PublicKey getPublicKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, URISyntaxException {
String key = env.getProperty("PUBLIC_KEY_DEMO");
key = key.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLICKEY-----", "").replace("\n", "");
byte[] keyBytes = Base64.getMimeDecoder().decode(key);
X509EncodedKeySpec spec = new X509EncodedKeySpec((keyBytes));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
我能够获得JWT
令牌,但是,我无法生成PublicKey
下面是 ExceptionStack:
java.security.SignatureException: Signature length not correct: got 255 but was expecting 256
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:189) ~[na:1.8.0_191]
at java.security.Signature$Delegate.engineVerify(Signature.java:1222) ~[na:1.8.0_191]
at java.security.Signature.verify(Signature.java:655) ~[na:1.8.0_191]
at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.doVerify(RsaSignatureValidator.java:63) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.isValid(RsaSignatureValidator.java:47) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.isValid(DefaultJwtSignatureValidator.java:47) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:351) ~[jjwt-0.9.1.jar:0.9.1]
请让我知道我做错了什么以及是否可以以更好的方式实施。
编辑
以下是我用来生成/验证 JWT 的方法。
public String generateToken()
throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, URISyntaxException {
PrivateKey privateKey = this.getPrivateKey();
Date date = new Date();
date.setTime(date.getTime() + 60 * 60 * 1000);
String jws;
jws = Jwts.builder()
.setAudience("jws-consumers")
.setIssuer("jws-issuer")
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "RS256")
.setExpiration(date)
.setIssuedAt(new Date())
.setSubject("nish")
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();
return jws;
}
public Object validateToken(String token) throws ExpiredJwtException, MalformedJwtException, SignatureException,
IllegalArgumentException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, URISyntaxException {
return Jwts.parser()
.setSigningKey(getPublicKey())
.parse(token)
.getBody();
}
这是生成的 JWT 的示例
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJqd3MtY29uc3VtZXJzIiwiaXNzIjoiandzLWlzc3VlciIsImV4cCI6MTU1MDE2NDc0NCwiaWF0IjoxNTUwMTYxMTQ0LCJzdWIiOiJuaXNoIn0.EbNzMIUc4HE6CwIDyURdYF-tE4z7rzM9_GbHpB-TlRror9HRO5bmGgXR7x9HOazmL3cTUPMd46s7QJ9cU_HIJYQu9pYIQzu3V2WZf0zpFevtFxBbGDU_UCM1fbdsgSrd8APSKt_mXbJGdzIA8L7O6gBnpvNowgEuNHYgMiRwL89GrT17c31WwIWSRfRubn-bYU62pd5wm5pMArvGBYi6f6EAoIdYsK-nlhKjOIsxjGigjYAohoooV_xv36_q5_8Iaxppl2yroxCeYCy6Jp9po3bjoLVu3k9vkD_-yUGoXr9e-LCktSS4Ndxq4KCVRI_Cf5Ix_ImcZrqFZLdb4UWGmA
解决方案
如果有人遇到同样的问题,我通过以下示例解决了这个问题。
我使用此处显示的命令生成了我的public
/private
键。
并更改了以下几行(使用 PRIVATE 而不是 PUBLIC 作为PRIVATE
密钥)
key = key.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLICKEY-----", "").replace("\n", "");
至
key = key.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
它发挥了魔力并且工作得非常好。
推荐阅读
- c++ - 如何将Boost.Spirit自定义点与Nabialek结合?
- xcode - 如何使用 Xcode 10 嵌入项目?
- python - 如何在python的不同文件中导入嵌套函数?
- c++ - 为什么我的代码打印错误的密文?
- python - 在输入 CNN 之前将图像标准化为浮点 0~1、浮点 -1~1 和整数 0~255 有什么区别?
- php - 为什么 pcntl_fork() 没有在 Laravel 控制器中定义?
- sql - 从每个唯一的 Skill_id 中找到一个随机 Set_id
- python-3.x - ValueError:形状(5,14)和(16,)未对齐:14(dim 1)!= 16(dim 0)
- xcode - OSX - Unidentified Developer 和捆绑格式不明确(可能是应用程序或框架)
- java - Android/MySQL:如何根据 MySQL 的值检查单选按钮