gpt4 book ai didi

java - 无法验证 Java 中的 jwt 签名

转载 作者:行者123 更新时间:2023-11-30 08:09:07 25 4
gpt4 key购买 nike

我正在尝试通过验证其签名来验证 JWT token 。但是在验证过程中我得到一个错误

java.security.SignatureException: Signature length not correct: got 342 but was expecting 256

.我假设签名是数据的加密 sha256 散列。在我的例子中,数据是 base64(header)+"."+base64(body)。这是我的代码:

static String certificate = "MIIDBjCCAe4CCQDmPif23IJerzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE1MDkyMjA3MDkwMFoXDTE2MDkyMTA3MDkwMFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALYjKc8pLFkAa45j6w6PHsroe7ijOCfhZmVtMCvZ8lINaP9mR8irOJHpLdJs4vpbxEZMqqLMhKjO7iUmXBmml37QRlJXY6f25essPkTdUmhiIrU/rIrZrCanvegXUHkvf4xvOQ1BTx/p5b1iIq3Wrk5Fox3pMigzqYhk4YuiJho8uabC9zyecmS3zIoRgwx+Vacel/ZW6r6YOlB6mblN9IvasvqWgDalegmMKOIZvwkpo/3mfzcGi5haWZZ3ufUqQjb4B7raJmfyrLnwi6XI9UzzGc04pCfIAsxTb5yM8cJQcJ/5VHF3h21eFJdZKyD2210gSq7/Y8Oda0dDXQchmFcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAmBm84PfwOe5sGemT9D4ImIYWp/1xrV6b0zeaDZ6Yi7sz9R3VKjfnAxUVOHA7GlMi8xHHdDu7VhVhAWyFCvITdG00K18xJuKap1bwzw3kr70lLQaFahV+zaWKfWAfV34tots3G/hMqdOv0a+I/5t/T7oKPCmm/IfCVKdC1tGbTji+hxVLpaAkn60RFNzLKGFwtSxv9ObxR5Hn88+wV48VAcEnwcUk2DjBi1fW6jnMcNJbVd+/oKBOwj7UK2Lk10Qaeet8KKh5fFKEpgx7D4ITwer0G/Je1NMv1/lfNzpKlTKoBureF5C6B+rJIesQ/dAfg6H/ggxbgVMuo6imIPVvrg==";
static String signedData = "Z5MwwjtXdypMQGNwmNNuCVmRcDVT24EgtwoDWalF4icxwz7jyB99Yg3262D7OsERewv4cOfdEz3bbOF-iG7YWXeSC9YZeO1tGapqlc8FRtAergSUZC7BcbFEx75MfSy7qLWYTOfdpJesQ23rOzjF7KdrAMJC_Y0T_r6RuBcZVyfT4P55kICETYyv7bBDXc9V8BJUf-QHDu6DaH7u6PSyeOmdzFInI_LwySnMlr3VahoUfUpJmauU8yHQUnFakJBgrMBe1Au9tS-HxtDVnHmoHQw8xGXsVQnEOa1aPAcVWy0v7hILUSmWNAG3IZ0JwUztQitgtnTTzXDszUxTbJ4YlQ";

static String data = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiJodHRwczovL2NpdHJpeHAuY29tOjg0NDMvIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZGQ5YjZhM2UtMjlkMS00MjU0LWE3NDYtZTAyOTQxNDQ0NTE3LyIsImlhdCI6MTQ0MjYyNjA0NSwibmJmIjoxNDQyNjI2MDQ1LCJleHAiOjE0NDI2Mjk5NDUsInZlciI6IjEuMCIsInRpZCI6ImRkOWI2YTNlLTI5ZDEtNDI1NC1hNzQ2LWUwMjk0MTQ0NDUxNyIsIm9pZCI6ImJkZDNmZDAyLTEyMzMtNGMxOC05NTRmLWJkNGFjMWYzOWU5OSIsInVwbiI6InNwQGNpdHJpeHAuY29tIiwic3ViIjoieUFfZTFzMmFOeFdvR3NSNzhfVWNYZkk5dERlYUM0QUozdXFZQXFDdllSbyIsImdpdmVuX25hbWUiOiJzIiwiZmFtaWx5X25hbWUiOiJwIiwibmFtZSI6InNwIiwiYW1yIjpbInB3ZCIsInJzYSJdLCJ1bmlxdWVfbmFtZSI6InNwQGNpdHJpeHAuY29tIiwiYXBwaWQiOiIyOWQ5ZWQ5OC1hNDY5LTQ1MzYtYWRlMi1mOTgxYmMxZDYwNWUiLCJhcHBpZGFjciI6IjAiLCJzY3AiOiJtZG1fZGVsZWdhdGlvbiIsImFjciI6IjEiLCJpcGFkZHIiOiI2My4xMTAuNTEuMTEiLCJkZXZpY2VpZCI6ImQyNzU3NzY0LWFiOTEtNDBiMS05MmM2LTViOWE4MWYxODNiYyJ9";

public static void main(String[] args) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
String certString = "-----BEGIN CERTIFICATE-----\r\n" + certificate + "\r\n-----END CERTIFICATE-----";
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
InputStream stream = new ByteArrayInputStream(certString.getBytes()); //StandardCharsets.UTF_8
java.security.cert.Certificate cert = cf.generateCertificate(stream);
PublicKey pk = cert.getPublicKey();


//verifying content with signature and content :
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify( pk );
sig.update(data.getBytes());

Boolean ret = sig.verify(signedData.getBytes());
} catch (CertificateException | SignatureException | NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}

最佳答案

JWT 的签名部分采用 base64url 编码 ( see JWS §7.1 ),因此您需要在验证前对其进行正确解码。

将行 Boolean ret = sig.verify(signedData.getBytes()); 替换为类似以下内容(使用 Apache Commons Codec 的 Base64 解码器),

 byte[] signature = org.apache.commons.codec.binary.Base64.decodeBase64(signedData);
Boolean ret = sig.verify(signature);

并且 JWT 上的签名应该为您验证。

话虽如此,我还是非常推荐使用库进行 JWT 处理。一个体面的库将为您处理类似的事情,并且还可以提供更多的 JWT 功能。

例如,以下使用 jose4j JWT library从证书中获取公钥后,可以替换问题代码中的内容。这不仅会根据规范验证签名,还会验证 JWT 中的声明以确保它仍然有效,已发给您等。

 JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setVerificationKey(pk)
.setRequireExpirationTime()
.setExpectedAudience("https://citrixp.com:8443/")
.setExpectedIssuer("https://sts.windows.net/dd9b6a3e-29d1-4254-a746-e02941444517/")
.build();

JwtClaims claims = jwtConsumer.processToClaims(data + "." + signedData);

System.out.println("Subject: " + claims.getSubject());
System.out.println("UPN: " + claims.getStringClaimValue("upn")); // or whatever, etc....

JWT 已过期几天,因此 processToClaims 将抛出异常,这正是您想要的。您可以在构建 JwtConsumer 时添加 .setEvaluationTime(NumericDate.fromSeconds(1442626055)) 以使其适用于给定的 JWT。

关于java - 无法验证 Java 中的 jwt 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32711149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com