java - 验证JWT签名PS256算法

标签 java security

嘿,大家好,我对 java 很陌生,我无法成功地通过充气城堡提供商验证 JWT 签名。JWT 是用 PS256 签名的。它总是返回一个错误值。请提前考虑!

这是我的示例代码:

String cert =
        "-----BEGIN CERTIFICATE-----\n" +
                "MIIDXTCCAkWgAwIBAgIEf7cAqTANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJS\n" +
                "bzESMBAGA1UECBMJQnVjaGFyZXN0MRIwEAYDVQQHEwlCdWNoYXJlc3QxDDAKBgNV\n" +
                "BAoTA0lTUzEMMAoGA1UECxMDSVNTMQwwCgYDVQQDEwNJU1MwHhcNMjAwMjA2MTM1\n" +
                "NTEwWhcNMjAwNTA2MTM1NTEwWjBfMQswCQYDVQQGEwJSbzESMBAGA1UECBMJQnVj\n" +
                "aGFyZXN0MRIwEAYDVQQHEwlCdWNoYXJlc3QxDDAKBgNVBAoTA0lTUzEMMAoGA1UE\n" +
                "CxMDSVNTMQwwCgYDVQQDEwNJU1MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" +
                "AoIBAQDhvsOgiLgZcQRzioyWZOfObGsbeMAtZXph1LlgMr+MYmXHLKQa7v1Xo/3o\n" +
                "JmzFfUj7pUsVo6og3j5n7CFpxvQ6CudVL2Tml+LHvRYy9jHs0dk44SRyEiMWYKw+\n" +
                "l6RttXSKrLyNLa+U8FWzQehkzsFJU4HsVxsoYkrZZP2WEKyHIG7ejFGdafRUv2GO\n" +
                "YRUNDzTcsDsy9M2ulMbYHj1Lzi3/sQ2N7A1xcEC7Bi6A012XOOPBpsNHmnZzZLpA\n" +
                "FZMCdb/8dTb9XHxDhEBdB5EsmDyCwS+cgj83tWxQIpT4ZU70uygXT28X1NgG0S7d\n" +
                "qVWZ3Pvocsttg8Eu+7SXO8K4uLOdAgMBAAGjITAfMB0GA1UdDgQWBBT1x4g7+S4Q\n" +
                "4p/jJKkLid/+m1U/ZDANBgkqhkiG9w0BAQsFAAOCAQEAuNRTUrDrbC1Iv9ECjMmA\n" +
                "qKkyT56lb3JdhpAP0O9yT/F3pFkUywikJPSc83m9lHc8KRI3KINspspj2XePDh9b\n" +
                "6oLXZwFG/tv4I8j3fKxpwO9BcTMyOoYRynHl8PxePWA+Xtg3P/yVhDqZBaTqAifB\n" +
                "A5QyN8AKh+Nt1mySCODFp76wJjvnCXdk1M7jGW38U92kNtC6I8Pv6li9xuRKZGyT\n" +
                "B9qQqsop3LtxS4fy719Gyytzc23B8NwFdLzPM0P0iJiz7aGU7uLsdBGe92GRrHf8\n" +
                "9A9DlBnqQwBLesw/fPzLt67hUnUaFg71rP1ZbFcT/yRhH8IEQhaQ29lSXmZjG6Tz\n" +
                "PA==\n" +
                "-----END CERTIFICATE-----";

CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bytes = new ByteArrayInputStream(cert.getBytes());
X509Certificate certificate1 = (X509Certificate) certFactory.generateCertificate(bytes);

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

String jwtS = "eyJ0eXAiOiJKV1QiLCJhbGciOiJQUzI1NiJ9.eyJjdXN0b21lcklkIjoiYSIsImFjY291bnRzIjoiYyIsImNvdW50cnlDb2RlIjoiYiJ9.KMrdAKLjQkQCE5GRa39pLdmAGcwIgNVreRsDf_jbQLDWeRoH_ChxZF9X8lV9wwJIJfC3mjH2sDwwnsn0Dw5q3OpM83VWDbHeQ9899_kfV1XDxdoUB54xGUsC95w3CP5eNXthLWn58l8areCATK-TesMnu1BNZ5jzBQohqns_a1NUDP0cWweWp477Fj2-nmuceNO0OihqnZ08gCdaXmgdrX73nlf9WNEXcgGpWQMhatdzB43vKBMBkfF1PudN-gm4s9QBYcGWRjZJrqUKRPbYZuLCs39N4WOX896nWaTGyiVCwcdfV1SDSGafqE_PfNu5kUezm31jy2Uk0p-KcyoSdQ";

JWT jwt = JWTParser.parse(jwtS);

SignedJWT jwsObject = (SignedJWT) jwt;
Base64URL signature = jwsObject.getSignature();

Signature sig = Signature.getInstance("SHA256withRSAandMGF1","BC");
System.out.println("Signature: " + signature.toJSONString());

sig.initVerify(certificate1);
sig.update(signature.decode());

boolean flagSig =  sig.verify(jwsObject.getSignature().decode());
System.out.println("Signature is valid: " + flagSig);

最佳答案

这就是你错的地方:

sig.update(signature.decode());

您正在尝试通过签名字节本身验证签名。

根据java.security.Signature :

Updating

Depending on the type of initialization, this will update the bytes to be signed or verified.

在您的情况下,要验证的数据是编码的header.payload,因此:

eyJ0eXAiOiJKV1QiLCJhbGciOiJQUzI1NiJ9.eyJjdXN0b21lcklkIjoiYSIsImFjY291bnRzIjoiYyIsImNvdW50cnlDb2RlIjoiYiJ9

如果您使用 JWT 库,它应该提供验证方法,并且使用该方法会更安全。

此外,如果您使用的是 Java 11+,则支持 RSASSA-PSS。这样就无需使用 BouncyCaSTLe。

关于java - 验证JWT签名PS256算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60097130/

相关文章:

Java+Kotlin Jar 只能与 Gradle 应用程序插件一起运行

javascript - 使用 Firebase 的 push()/childByAutoID 生成的名称的唯一性保证是什么?

security - 同事可以访问 Git 本地分支

web-services - 请求中需要 Uname/Password 的 Web 服务的代理安全服务

java - 出于安全目的,如何在某些节点上禁用 Hazelcast 分布式 IExecutorService?

java - 如何在 Spring Boot 中有条件地 Autowiring ?

java - Java Swing中adapter和listener使用的一些疑惑

java - Jmeter 中的 Beanshell 断言成功消息

java - 如何计算Android设备的屏幕开启时间

ruby - 如何只允许访问某些特定的 ruby​​ 类?