JWT 解密,但抛出 mac check failed 错误

Posted

技术标签:

【中文标题】JWT 解密,但抛出 mac check failed 错误【英文标题】:JWT decrypts, but throws a mac check failed error 【发布时间】:2017-09-22 21:33:54 【问题描述】:

我有一个 jhipster spring boot 应用程序,它接受由第三方生成的令牌,该令牌已用我们的公钥加密。我有一个 JWTFilter,它使用我们的私钥解密令牌并创建一个存储在安全上下文中的身份验证对象。一旦执行到达控制器,我打算从安全上下文中提取用户名和密码,以便我可以将 API 调用回第三方应用程序。

这在某种程度上在我们的集成环境中起作用,其中第三方具有指向我们应用程序正在运行的实例的链接。为了在本地进行测试,我点击了集成环境中的链接,并复制了令牌。然后我从 Postman 向我在本地运行的应用程序的一个实例发出请求,并在标头中添加了令牌,就像我们的 js 客户端一样。

我正在使用“com.nimbusds:nimbus-jose-jwt:4.23”进行解密,但出现“MAC 检查失败”错误。我可以在调试器中将 macCheckPassed 的值更改为 true,解密将完成,允许我查看声明并将它们加载到安全上下文中。但是,其他一些过滤器正在捕获我的 hack,请求被拒绝并出现授权错误。

public static byte[] decryptAuthenticated(final SecretKey secretKey,
                                      final byte[] iv,
                                      final byte[] cipherText,
                                      final byte[] aad,
                                      final byte[] authTag,
                                      final Provider ceProvider,
                      final Provider macProvider)
    throws JOSEException 


    // Extract MAC + AES/CBC keys from input secret key
    CompositeKey compositeKey = new CompositeKey(secretKey);

    // AAD length to 8 byte array
    byte[] al = AAD.computeLength(aad);

    // Check MAC
    int hmacInputLength = aad.length + iv.length + cipherText.length + al.length;
    byte[] hmacInput = ByteBuffer.allocate(hmacInputLength).
        put(aad).
        put(iv).
        put(cipherText).
        put(al).
        array();
    byte[] hmac = HMAC.compute(compositeKey.getMACKey(), hmacInput, macProvider);

    byte[] expectedAuthTag = Arrays.copyOf(hmac, compositeKey.getTruncatedMACByteLength());

    boolean macCheckPassed = true;

    if (! ConstantTimeUtils.areEqual(expectedAuthTag, authTag)) 
        // Thwart timing attacks by delaying exception until after decryption
        macCheckPassed = false;
    

    byte[] plainText = decrypt(compositeKey.getAESKey(), iv, cipherText, ceProvider);

    if (! macCheckPassed) 

        throw new JOSEException("MAC check failed");
    

    return plainText;

什么是 MAC 检查?我认为这与令牌的起源有关。类似于使用源系统的 MAC id 对令牌进行加密的内容,当它与我当前的主机不同步时会引发错误。

如果解密通过,还有什么其他过滤器会拒绝请求?我应该设置其他标志以便框架接受请求吗?

【问题讨论】:

【参考方案1】:

JWE 规范要求 authenticated encryption,以确保纯文本不仅被加密,而且还防止被篡改。确保内容加密后为HMAC is applied。

“Mac 检查失败”错误可能意味着两件事 - 生成原始 JWE / JWT 的库错误地应用了 HMAC,或者 JWE / JWT 在传输过程中被修改。

【讨论】:

以上是关于JWT 解密,但抛出 mac check failed 错误的主要内容,如果未能解决你的问题,请参考以下文章

带有 ***Service 的 Android 防火墙。响应已传递,但抛出 SocketTimeoutException

尽管未设置但抛出 E_STRICT 消息

Django Ajax 表单工作但抛出 500(内部服务器错误)

尝试在 JAVA Spring,@AutoWired 过滤器服务,但抛出 NPE

流星对象在控制台中可用,但抛出“无法读取属性 findOne of undefined”

使用appium在android浏览器上运行selenium webdriver脚本,在模拟器上启动浏览器但抛出chromedriver异常