【问题标题】:Cannot Verify JWT Using x5c (x509) public Certificate无法使用 x5c (x509) 公共证书验证 JWT
【发布时间】:2019-08-09 02:45:47
【问题描述】:

更新 我正在尝试使用下面的 x5c / x509 公钥值以编程方式验证 JWT 访问令牌。我可以通过将令牌和 x5c 值插入外部网站而不是以编程方式使用 JavaScript / jsrsasign 来实现这一点。任何建议将不胜感激。

这是 OIDC 提供商的公共 JSON Web 密钥集。

    {
        "keys": [
            {
                "kty": "RSA",
                "kid": "server",
                "use": "sig",
                "alg": "RS256",
                "n": "gLZO9w1OT_SWO-KbqiU0k3HevHggiY70XbDqgE1YaqhD-MwFUWNudExzF3oB28NYWYg5v6CJY0F-pUNtgukDM6ARDlh0n4xIvBRlnUnCTCx7pYOjpfXbTv49tlXmh4-ddh8EeQBLrF92u5UYs0tnZd8843mvYWohUNH1X1hM08-hpk7xCiy4XdwbeSlH757D2d5E0J0dGtZ744-dB2ZRCw2Vms_mk4Yyny4ifx2j2gIhikbb7WGmsTR2sWrtuhgZ_EBNUvrD0O54xbhQNTTFQ1pi9UZxo_gYc5Gp5fLcSOK6SDBKXbDS5hhy1vFyoa0xdgFv-xpem7YzmkKqzfjC9w",
                "e": "AQAB",
                "x5c": [
                    "MIIDMDCCAhigAwIBAgIEFIopYzANBgkqhkiG9w0BAQsFADBaMQkwBwYDVQQGEwAxCTAHBgNVBAgTADEJMAcGA1UEBxMAMQkwBwYDVQQKEwAxCTAHBgNVBAsTADEhMB8GA1UEAxMYZmNpc2Rldi5pY2UuaWJtY2xvdWQuY29tMB4XDTE4MTAwMTE4MTYyOFoXDTI4MDkyODE4MTYyOFowWjEJMAcGA1UEBhMAMQkwBwYDVQQIEwAxCTAHBgNVBAcTADEJMAcGA1UEChMAMQkwBwYDVQQLEwAxITAfBgNVBAMTGGZjaXNkZXYuaWNlLmlibWNsb3VkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIC2TvcNTk/0ljvim6olNJNx3rx4IImO9F2w6oBNWGqoQ/jMBVFjbnRMcxd6AdvDWFmIOb+giWNBfqVDbYLpAzOgEQ5YdJ+MSLwUZZ1Jwkwse6WDo6X1207+PbZV5oePnXYfBHkAS6xfdruVGLNLZ2XfPON5r2FqIVDR9V9YTNPPoaZO8QosuF3cG3kpR++ew9neRNCdHRrWe+OPnQdmUQsNlZrP5pOGMp8uIn8do9oCIYpG2+1hprE0drFq7boYGfxATVL6w9DueMW4UDU0xUNaYvVGcaP4GHORqeXy3EjiukgwSl2w0uYYctbxcqGtMXYBb/saXpu2M5pCqs34wvcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdtN9znA9a6luPAQurcQn8kJBlllslRWsNPMhPWpMtYaMLx6JhmDICGbaYZBGUboedwnUaEk6tE2b+EVlUE/tnaKVJms2cmCCFExQQrTHmRfFI/Vi/esVqAnz1E2dB61LMnQ2AeebXAZ/C7hRt1uXVboXr5Zokppr4FRS9QsjSK4dhcXxhfglTKJOPZ4dkSexhe6hybpL8XdGhoyf2SyNXCy5iYX0zQ5BmJaLimOcJyasZ/A7/YgsVbQyAe6Ubno6/sIUuOZ+J+snZsBSLViqcftGVPUkIWamv/yNQcEJrDWa4C+sr+9Yb7uFjuj4gDY0jvGkGmu53g0K8Vks+IfAdQ=="
                ],
                "x5t#S256": "nTAGJuFFrm-vNBdkLVNmuePwTmlXr0T87IppgJPRT9k"
            }
        ]
    }

这是我用来通过 x5c 验证访问令牌的代码。我的印象是我应该使用 x5c 值,但如果有另一种适合我的方式。只需要在keys下用上面的值验证token即可。

// break line every 64 characters.

x5cValue = x5cValue.replace(/(.{64})/g, "$1\n");

// base64 decode

var x5cValueAtob = atob(x5cValue);

// Add Begin / END certificate

x5cValue = "-----BEGIN CERTIFICATE-----\n" + x5cValueAtob + "\n-----END CERTIFICATE-----";

var decoded = KJUR.jws.JWS.verify(accessTokenJson, rawContent, ["RS256"]);

我应该在 base64 解码之前/之后将 BEGIN / END PUBLIC KEY 字符串添加到 x5c 值吗?是的,感谢亚当

验证前是否需要处理 x5c 值?

返回的响应 - 解码:假

提前谢谢你。

【问题讨论】:

  • 我尝试在 base64 解码之前添加以下内容并得到相同的错误。 x5cValue = "-----BEGIN CERTIFICATE-----" + x5cValue + "-----END CERTIFICATE-----";
  • 实际上 Adam 你让我想到了,我添加了 BEGIN / END 文本和每 64 个字符的换行符。所以现在我像这样发送来验证并且错误已更改为 - false。我想我越来越近了:)
  • 我不知道,但我认为您仍然需要解码开始证书和结束证书之间的 x5cValue,因此它是 -----BEGIN CERTIFICATE-----${atob(x5cValue)}-----END CERTIFICATE-----。不过,我对一件事感到好奇,您需要验证令牌,还是只需对其进行解码以获取其内容?
  • 谢谢亚当,尝试了你的建议。更新了上面的代码以显示。仍然返回错误。

标签: javascript encryption jwt x509 jwk


【解决方案1】:

此答案可能无法帮助您回答所有问题,但我必须编写它以提高解决方案的安全性。

我觉得我应该使用 x5c 值,
验证前是否需要处理 x5c 值?

从安全的角度来看 - 不要使用 x5c 证书直接验证签名。在这种情况下,任何人都可以提供自己的证书并欺骗任何身份。

如果 x5t / x5t#S256 标头的目的是识别签名者 - 检查您信任指定 iss 下的 x5c 或 x5t#S256(或其颁发者)提供的证书,然后才您应该验证签名。 x5t 标头使您的服务能够验证来自多个 IdP(身份提供者/令牌颁发者)的令牌或启用更新签名者的证书,而不会失去对服务提供者的信任。

如果您只信任使用单个证书的单个身份提供者,您可以直接使用提供者的证书,而无需对提供的标头进行任何操作。

对于解决方案 - 似乎 Adam 在 cmets 中是正确的,我也建议您使用 KEYUTIL 来加载/解析证书

【讨论】:

    【解决方案2】:

    我花了一天时间挠头,终于让它像这样工作了

    public static PublicKey getPublicKey(String x5c) throws CertificateException, IOException {
        System.out.println(" x5c ="+x5c);
        String stripped = x5c.replaceAll("-----BEGIN (.*)-----", "");
        stripped = stripped.replaceAll("-----END (.*)----", "");
        stripped = stripped.replaceAll("\r\n", "");
        stripped = stripped.replaceAll("\n", "");
        stripped.trim();
        System.out.println(" stripped ="+stripped);
        byte[] keyBytes = Base64.decode(stripped);
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
        X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(keyBytes));
        return cer.getPublicKey();
    
    }
    

    【讨论】:

      猜你喜欢
      • 2010-09-25
      • 1970-01-01
      • 2016-02-03
      • 2015-06-16
      • 1970-01-01
      • 2011-09-02
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多