php - 在 JWT Token 创建过程中了解 RS256 和 SHA256
问题描述
我正在使用 PHP 中的私钥创建 JWT 令牌。为此,我正在使用 OpenSSL 库。在任何事情之前,我将分享我的代码:
PHP
$header = [
self::ALG => self::RS256,
self::TYP => self::JWT
];
$payload = [
"iss" => $this->getClientID(),
"iat" => time(),
"exp" => time()+999
];
$header = base64_encode(json_encode($header));
$payload = base64_encode(json_encode($payload));
$token = $header.".".$payload;
$pkey = openssl_pkey_get_private($this->getPrivateKey(), $this->getPassPhrase());
openssl_sign($token, $signature, $pkey, 'sha256'); //no algorithm specifically for rs256
$sign = base64_encode($signature);
return $token.".".$sign;
因此,此 JWT 令牌将用于在我尝试访问的服务器中进行身份验证。但是我从外部服务器得到响应,因为Bad Request
我的 JWT 令牌创建中发生了问题。
使用相同的凭据,我尝试使用库在 javascript 中jsrsasign
,然后它给了我正确的响应。
JAVASCRIPT
// Header
var oHeader = { alg: 'RS256', typ: 'JWT' };
// Payload
var oPayload = {};
var tNow = rs.KJUR.jws.IntDate.get('now');
var tEnd = tNow + 1000;
oPayload.iss = "playground.pizza";
oPayload.iat = tNow;
oPayload.exp = tEnd;
var sHeader = JSON.stringify(oHeader);
var sPayload = JSON.stringify(oPayload);
var pkey = "my private key" //I replaced all the new line with \n here and had in one line
var prvKey = rs.KEYUTIL.getKey(pkey, "my_pass_phrase");
var sJWT = rs.KJUR.jws.JWS.sign("RS256", sHeader, sPayload, prvKey);
ultraSecureToken = sJWT;
我可以清楚地看到的一个区别是,对于signature generation function
php 端,我sha256
作为算法传递,而在 JavaScriptRS256
中传递。
我读到 sha256 只是一种散列算法,而 RS256 用于编码,但在我在 php 中找到的所有库中,它们sha256
仅在内部传递openssl_sign
函数。并且openssl_sign
没有 RS256 作为算法参数。
所以,首先我哪里出错了。
其次,有没有一种方法可以在 php.ini 中使用 RS256 生成签名。
PS:我正在寻找 php 中的解决方案。
解决方案
的返回值
KJUR.jws.JWS.sign
由以点分隔的三部分组成。第一部分是 Base64url 编码的 JSON 字符串sHeader
,第二部分是 Base64url 编码的 JSON 字符串sPayload
,第三部分是 Base64url 编码的签名。要签名的数据由前两部分组成,包括分隔两部分的点。RS256表示使用带有 RSASSA-PKCS1-v1_5 填充的 SHA256 和 RSA 进行签名。这也可以很容易地在线验证,例如在这里,将SHA256withRSA
被选为算法。openssl_sign
还使用带有 RSASSA-PKCS1-v1_5 填充的 RSA,因此使用 SHA256 创建相同的签名,假设应用了相同的密钥和相同的要签名的数据。jsrsasign
使用Base64 url 编码(RFC4648,第 5 节),而 PHP(或更准确地说是base64_encode
- 方法)使用标准Base64 编码(RFC4648,第 4 节),这很可能是问题的原因之一。这意味着当前 PHP 代码中的编码必须更改为 Base64url,例如此处。当然,PHP 代码中的底层 JSON 字符串(
$header
和$payload
)$token
也必须与 JavaScript 代码中的对应部分相同,否则签名会有所不同。由于 PHP 代码不完整,因此无法检查这可能是问题的另一个原因。
推荐阅读
- wso2 - 带有 SAML SSO 的 WSO2AM - 无法创建应用程序密钥
- python - 模拟一个类方法并将 self 参数传递给 Mock 的副作用
- swift - 使用 Swift 在收件箱中打开包含特定邮件的邮件应用
- mysql - Telerik Report Designer 呈现空白报告
- angular - 读取承诺值并将其传递给可观察对象的下一个方法
- terraform - 有没有办法列出 terraform 资源的所有输入变量?
- gradle - 带有 Lombok 的 Gradle 随机中断
- html - 从 jQuery 1.12.4 迁移到 3.3.0 问题
- php - 如果它是数字数组中的第 10 个数字,则在 PHP 中标记或标记一个数值
- node.js - Node JS,导出一个类并使用不同的名称对其进行 cosumin