KJUR jws jsrsasign:无法在 JWT.io 上验证 ES256 令牌

2024-02-15

我们正在尝试使用 KJUR jws 库为 Apple Search Ads 制作 JWT 令牌。我们使用的是Apple的API文档:

https://developer.apple.com/documentation/apple_search_ads/implementing_oauth_for_the_apple_search_ads_api https://developer.apple.com/documentation/apple_search_ads/implementing_oauth_for_the_apple_search_ads_api

我们正在生成私钥(prime256v1 曲线):

openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem

接下来我们从私钥生成公钥:

openssl ec -in private-key.pem -pubout -out public-key.pem

接下来我们设置标头和有效负载:

var tNow = KJUR.jws.IntDate.get('now');
var tEnd = KJUR.jws.IntDate.get('now + 1day');
var teamId = 'SEARCHADS.xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
var keyId = 'xxxxxx-xxxx-xxxx-xxxxxxxxxxx';
var privateKey = `-----BEGIN EC PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END EC PRIVATE KEY-----`;
  
var oHeader = {
  "alg": "ES256",
  "kid": keyId
}
  
var oPayload = {
  "iss": teamId,
  "iat": tNow,
  "exp": tEnd,
  "aud": "https://appleid.apple.com",
  "sub": clientId
}
   
var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
  
var sKey = KEYUTIL.getKey({d: privateKey, curve: 'prime256v1'});  
var sResult = KJUR.jws.JWS.sign('ES256', sHeader, sPayload, sKey);

接下来我们尝试在 jwt.io 上验证 JWT 令牌(它已生成令牌),但无法验证。 Apple 搜索广告还会抛出 invalid_client 消息。我缺少什么?有人知道我在这里做错了什么吗?

亲切的问候,

杰克·夸克曼


该问题是由于密钥导入不正确造成的。

发布的密钥是 SEC1 格式的 PEM 编码私钥。在getKey()密钥以 JWK 格式传递,指定原始私钥d。 PEM 编码的 SEC1 密钥用作以下值d。这是不正确的,因为原始私钥与 SEC1 密钥不同,而只是包含在其中。

要解决此问题,必须正确导入密钥。jsrsasign还支持导入 SEC1 格式的 PEM 编码密钥,但它还需要 EC 参数 s。例如here https://kjur.github.io/jsrsasign/api/symbols/KEYUTIL.html#.getKey. For prime256v1 aka secp256r1这是:

-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----

这些可以被创建,例如使用 OpenSSL 作为密钥生成过程的一部分:

openssl ecparam -name secp256r1 -genkey

至此,固定的 JavaScript 代码为:

var tNow = KJUR.jws.IntDate.get('now');
var tEnd = KJUR.jws.IntDate.get('now + 1day');
var teamId = 'SEARCHADS.xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
var keyId = 'xxxxxx-xxxx-xxxx-xxxxxxxxxxx';
var privateKey = `-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIK1vV4iLOPym9KvJJU5hd6CMEp+DTt8QI7NPBdJSf+VDoAoGCCqGSM49
AwEHoUQDQgAEMpHT+HNKM7zjhx0jZDHyzQlkbLV0xk0H/TFo6gfT23ish58blPNh
YrFI51Q/czvkAwCtLZz/6s1n/M8aA9L1Vg==
-----END EC PRIVATE KEY-----`;
  
var oHeader = {
  "alg": "ES256",
  "kid": keyId
}
  
var oPayload = {
  "iss": teamId,
  "iat": tNow,
  "exp": tEnd,
  "aud": "https://appleid.apple.com",
  "sub": "clientId"
}
   
var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
  
var sKey = KEYUTIL.getKey(privateKey);  
var sResult = KJUR.jws.JWS.sign('ES256', sHeader, sPayload, sKey);

document.getElementById("jwt").innerHTML = sResult;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.4.0/jsrsasign-all-min.js"></script>
<p style="font-family:'Courier New', monospace;" id="jwt"></p>

使用此代码生成的 JWT 可以成功验证https://jwt.io/ https://jwt.io/使用以下公钥(与上面的私钥关联):

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMpHT+HNKM7zjhx0jZDHyzQlkbLV0
xk0H/TFo6gfT23ish58blPNhYrFI51Q/czvkAwCtLZz/6s1n/M8aA9L1Vg==
-----END PUBLIC KEY-----

当然,正如评论中提到的,私钥也可以转换为 PKCS#8 格式(例如使用 OpenSSL)。导入同样可以使用getKey()(或者也可以KEYUTIL.getKeyFromPlainPrivatePKCS8PEM()):

var tNow = KJUR.jws.IntDate.get('now');
var tEnd = KJUR.jws.IntDate.get('now + 1day');
var teamId = 'SEARCHADS.xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
var keyId = 'xxxxxx-xxxx-xxxx-xxxxxxxxxxx';
var privateKey = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrW9XiIs4/Kb0q8kl
TmF3oIwSn4NO3xAjs08F0lJ/5UOhRANCAAQykdP4c0ozvOOHHSNkMfLNCWRstXTG
TQf9MWjqB9PbeKyHnxuU82FisUjnVD9zO+QDAK0tnP/qzWf8zxoD0vVW
-----END PRIVATE KEY-----`;
  
var oHeader = {
  "alg": "ES256",
  "kid": keyId
}
  
var oPayload = {
  "iss": teamId,
  "iat": tNow,
  "exp": tEnd,
  "aud": "https://appleid.apple.com",
  "sub": "clientId"
}
   
var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
  
var sKey = KEYUTIL.getKey(privateKey);  
//var sKey = KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(privateKey); // works also
var sResult = KJUR.jws.JWS.sign('ES256', sHeader, sPayload, sKey);

document.getElementById("jwt").innerHTML = sResult;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.4.0/jsrsasign-all-min.js"></script>
<p style="font-family:'Courier New', monospace;" id="jwt"></p>

如果密钥导入为 JWK,则x and y除了原始私钥之外,还必须指定原始公钥的坐标d。使用 ASN.1 解析器最容易确定这些值,例如https://lapo.it/asn1js/ https://lapo.it/asn1js/。此外,密钥类型(kty) 必须指定,曲线标识符的关键字是crv:

var tNow = KJUR.jws.IntDate.get('now');
var tEnd = KJUR.jws.IntDate.get('now + 1day');
var teamId = 'SEARCHADS.xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
var keyId = 'xxxxxx-xxxx-xxxx-xxxxxxxxxxx';
var privateKey = `rW9XiIs4_Kb0q8klTmF3oIwSn4NO3xAjs08F0lJ_5UM`;
var publicKeyX = `MpHT-HNKM7zjhx0jZDHyzQlkbLV0xk0H_TFo6gfT23g`;
var publicKeyY = `rIefG5TzYWKxSOdUP3M75AMArS2c_-rNZ_zPGgPS9VY`;
  
var oHeader = {
  "alg": "ES256",
  "kid": keyId
}
  
var oPayload = {
  "iss": teamId,
  "iat": tNow,
  "exp": tEnd,
  "aud": "https://appleid.apple.com",
  "sub": "clientId"
}
   
var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
  
var sKey = KEYUTIL.getKey({kty: "EC", d: privateKey, x: publicKeyX, y: publicKeyY, crv: 'prime256v1'});  
var sResult = KJUR.jws.JWS.sign('ES256', sHeader, sPayload, sKey);

document.getElementById("jwt").innerHTML = sResult;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.4.0/jsrsasign-all-min.js"></script>
<p style="font-family:'Courier New', monospace;" id="jwt"></p>

这些代码生成的 JWT 可以在上成功验证https://jwt.io/ https://jwt.io/使用上面的公钥。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

KJUR jws jsrsasign:无法在 JWT.io 上验证 ES256 令牌 的相关文章

随机推荐

  • 使用jquery设置输入html字符串的值

    我在字符串中有 HTML 片段 如下所示 var htmlString
  • NSSpeechSynthesizer 更改语言

    我正在编写一个基于 Cocoa Book 示例的简单程序 该程序使用 NSSpeechSynthesizer 来说出短语 我想知道如何更改用于合成阶段的语言 import PHAppDelegate h implementation PHA
  • 缺少 pdb 文件

    我正在 wince7 设备上调试我的应用程序 几分钟后 我收到一个错误 没有为任何调用堆栈帧加载任何符号 无法显示源代码 我注意到模块列表中有 1 个 dll 缺少 pdb 文件 它的名称是 System Drawing dll 我注意到在
  • 中止读取文件时 PHP 页面超时

    我有一个简单的 php 视图 如下所示 header Content Type image png readfile this gt image exit 在这个例子中 this gt image例如 data pictures thumb
  • 获取 Quicktime 视频信息

    有没有办法获取 QuickTime 视频信息 在谷歌搜索中 我发现 QT 的一个 cl 选项已损坏 我正在寻找 pasp 长度 音频通道 音频分配 拍手以及经常使用程序 Dumpster 找到的各种其他属性 使用 ffmpeg 无法获得大部
  • 如何使用 Webpack 创建与容器应用程序共享库的微前端捆绑包?

    我有一个任务 拥有具有单 Spa 框架的微前端 门户 主应用程序 通过 url 加载所有其他 js 代码 微前端 1 基于 React 微前端 2 基于 React 所以我的问题只有一个 我不想重复供应商库 如react react dom
  • 存储下拉值,什么是好方法

    想象一下 您有一个网站 其中有多个下拉菜单 这些下拉菜单是从后端数据库填充的 目标是将这些值存储在数据库中 并在渲染表单时检索它们 我见过使用两种方法 1 每种列表类型一张表 profession type id value hobby t
  • ASP.NET MVC 从 C# 代码创建绝对 url

    如何从 C 代码生成绝对 url 我想生成一个像这样的网址 localhost controller action id 有没有办法在 C 中做到这一点 就像在视图中完成它一样 它不会在控制器内部生成 而是在 ViewModel 内部生成
  • $.getJSON 获取 JSONP 数据

    我通过以下方式使用 getJSON 来接收警报 但没有运气 这是代码 并且ticker js文件只有以下行 ticket IBM price 14 57 它应该收到警报 14 57 但我没有收到警报 如果您想查看它的实际效果 可以尝试该链接
  • java.awt.Robot 的本机源代码

    我正在尝试找到 Java Robot 函数的本机实现 我找到了Windows的实现here http cr openjdk java net ohair openjdk7 jdk7 build copyright webrev jdk sr
  • “MongoDB Compass”无法打开,因为苹果无法检查它是否有恶意软件

    当我尝试在 macOS Catalina 上安装 MongoDB Compass 时 出现以下情况 MongoDB Compass can t be opened because Apple cannot check it for mali
  • 可以处理 HTTPS 的 WebBrowser 控件

    我正在寻找 NET 中可以处理 HTTPS 的 WebBrowser 控件的替代品 这个问题 https stackoverflow com questions 790542 replacing net webbrowser control
  • 使用 dash python 更改 bootstrap nav-pills 样式

    Dash 允许使用我们自己的 CSS 样式表 但是 如果您在科学领域并且不熟悉 CSS 则可以使用 Bootstrap 组件 这使得样式和页面布局非常容易组合在一起 这是在 dash 中创建侧边栏的标准示例 This app creates
  • Android 6.0 Marshmallow 停止显示垂直 SeekBar 拇指

    我一直在使用这个基本的包装器 https stackoverflow com a 28397530 250340在 SeekBar 周围 但发现它隐藏了拇指 或者做了一些时髦的事情 比如在棉花糖下的白色背景上将其变成白色 我使用 AS Bl
  • 企业报告解决方案[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • ListView Flutter 的单选

    我正在尝试实施一个listView在我的应用程序中进行单选 这样一旦点击列表中的项目 按下的项目颜色状态就会与其他项目不同 我已经做了我所知道的一切 但效果并不好 问题是 即使我的实现在按下时更新每个项目的状态 它也不会将其他项目重置为其初
  • 无法将 Web.Http.Results.JsonResult 隐式转换为 Web.Mvc.JsonResult

    我已经在控制器上设置了这个测试方法 以消除任何复杂性 根据我通过搜索找到的所有结果 这应该可行 我不确定我在这里缺少什么 public JsonResult test return Json new id 1 这是我得到的错误 无法将类型
  • 在 PHP 5 中如何通过引用传递对象?

    在 PHP 5 中 您是否需要使用 修饰符通过引用传递 例如 class People p new People function one a a null function two a a null 在 PHP4 中你需要 修改器来在更改
  • 缓冲读取器和文件读取器以及扫描器类之间的区别[重复]

    这个问题在这里已经有答案了 谁能解释一下班级之间的区别BufferedReader FileReader and Scanner 当我想读取文本文件时该使用哪一个 Well FileReader只是一个Reader它使用平台默认编码 urg
  • KJUR jws jsrsasign:无法在 JWT.io 上验证 ES256 令牌

    我们正在尝试使用 KJUR jws 库为 Apple Search Ads 制作 JWT 令牌 我们使用的是Apple的API文档 https developer apple com documentation apple search a