简体   繁体   English

为什么 JWS 签名验证失败?

[英]Why is verification failing for a JWS signature?

I'm trying to sign the message with a detached payload using the Nimbus JOSE JWT library in Java. The verification goes through locally but whenever I try to send it to the server using Postman I get: "The signature header x-jws-signature was parsed and has a valid JOSE header that complies with the specification. However, the signature itself could not be verified"我正在尝试使用 Java 中的 Nimbus JOSE JWT 库使用分离的有效负载对消息进行签名。验证在本地进行,但每当我尝试使用 Postman 将其发送到服务器时,我得到: "The signature header x-jws-signature was parsed and has a valid JOSE header that complies with the specification. However, the signature itself could not be verified"

 JWSSigner signer = new RSASSASigner(privateKey);

        HashMap<String, Object> criticalParameters = new HashMap<>();
        criticalParameters.put("http://openbanking.org.uk/iat", 1501497671);
        criticalParameters.put("http://openbanking.org.uk/iss", orgId);
        criticalParameters.put("http://openbanking.org.uk/tan", "openbankingtest.org.uk");

        JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.PS256)
                .type(JOSEObjectType.JOSE)
                .keyID(keyID)
                .criticalParams(criticalParameters.keySet())
                .customParams(criticalParameters)
                .build();

        // With encoding the payload
        JWSObject jwsObject = new JWSObject(header, payload);
        jwsObject.sign(signer);

        String jws = jwsObject.serialize(true);


        JWSObject parsedJWSObject = JWSObject.parse(jws, payload);

        if (parsedJWSObject.verify(new RSASSAVerifier(publicKey, criticalParameters.keySet()))) {
            System.out.println(parsedJWSObject.serialize(true));
        } else {
            System.out.println("Invalid");
        }
        //=============================

        // Without encoding the payload
        Base64URL signature = signer.sign(header, (header.toBase64URL().toString() + "." + payload).getBytes());
        JWSVerifier verifier = new RSASSAVerifier(publicKey, criticalParameters.keySet());

        boolean isValid = verifier.verify(header, (header.toBase64URL().toString() + "." + payload).getBytes(), signature);
        System.out.println(header.toBase64URL().toString() + ".." + signature.toString());
        System.out.println(isValid);
        //=============================

Both of the functions successfully sign and verify the JWS but for some reason, it doesn't work.这两个函数都成功地签署并验证了 JWS,但由于某种原因,它不起作用。 If it helps, I'm trying to access the Open Banking API.如果有帮助,我正在尝试访问 Open Banking API。

Got a similar problem very recently.最近遇到了类似的问题。 I would suggest you to check the following:我建议您检查以下内容:

  • Is the payload in the request exactly the same as the one used for the JW signature (without escaping or formatting characters)?请求中的负载是否与用于 JW 签名的负载完全相同(没有 escaping 或格式化字符)?
  • What's the order of the JSON properties in the payload and does the financial entity you are trying to interact with have specific requirements when it comes to the order of those JSON fields?有效负载中 JSON 属性的顺序是什么?当涉及到这些 JSON 字段的顺序时,您尝试与之交互的金融实体是否有特定要求?

I know it's very questionable to expect the json properties in the payload to be in a specific order, but by experience I found out that some open banking implementations are assuming a specific order (not even alphabetical) and they will fail with that error when the order is not the one they expect.我知道期望有效负载中的 json 属性按特定顺序排列是非常值得怀疑的,但根据经验,我发现一些开放式银行实现采用特定顺序(甚至不是字母顺序),当订单不是他们期望的。

JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.PS256)
            .type(JOSEObjectType.JOSE)
            .keyID(keyID)
            .criticalParams(criticalParameters.keySet())
            .customParams(criticalParameters)
            .build();
     //simplyfy your payload json string before..remove all spaces.
      Gson gson = new GsonBuilder().disableHtmlEscaping().create();
     JsonElement el = JsonParser.parseString(payload);
    String simplePayload=gson.toJson(el);
    // With encoding the payload
    Payload detachedPayload =new Payload(new Base64URL(simplePayload).toString());
    JWSObject jwsObject = new JWSObject(header, detachedPayload );
    jwsObject.sign(signer);

    String jws = jwsObject.serialize(true);

  JWSObject parsedJWSObject = JWSObject.parse(jws, detachedPayload );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM