【问题标题】:Understanding RS256 and SHA256 during JWT Token creation在 JWT Token 创建过程中了解 RS256 和 SHA256
【发布时间】:2020-03-29 03:14:00
【问题描述】:

我正在使用 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 令牌创建中出现了问题。

使用相同的凭据,我尝试使用库jsrsasign 使用javascript,然后它给了我正确的响应。

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;

我可以清楚地看到一个区别是,对于 php 端的 signature generation function,我将 sha256 作为算法传递,而在 JavaScript 中传递 RS256

我了解到 sha256 只是一种散列算法,而 RS256 用于编码,但在我在 php 中找到的所有库中,它们在内部仅在 openssl_sign 函数中传递 sha256。而且openssl_sign没有RS256作为算法参数。

那么,首先我哪里出错了。

其次,有没有一种方法可以在 php.ini 中使用 RS256 生成签名。

PS:我正在寻找 php 中的解决方案。

【问题讨论】:

    标签: php jwt rsa sha


    【解决方案1】:
    • KJUR.jws.JWS.sign 的返回值由以点分隔的三部分组成。第一部分是 Base64url 编码的 JSON 字符串 sHeader,第二部分是 Base64url 编码的 JSON 字符串 sPayload,第三部分是 Base64url 编码的签名。要签名的数据由前两部分组成,包括分隔两部分的点。 RS256 表示使用带有 RSASSA-PKCS1-v1_5 填充的 SHA256 和 RSA 进行签名。这也可以很容易地在线验证,例如here,其中SHA256withRSA 将被选为算法。

    • openssl_sign 还使用带有 RSASSA-PKCS1-v1_5 填充的 RSA,因此使用 SHA256 创建 same 签名,假设应用了相同的密钥和相同的要签名的数据。

    • jsrsasign 使用 Base64 url-encoding (RFC4648, sect. 5),而 PHP(或更准确地说是 base64_encode-method)使用 standard Base64-encoding (RFC4648, sect. 4),它最有可能是问题的原因之一。这意味着当前 PHP 代码中的编码必须更改为 Base64url,例如here.

    • 当然,PHP 代码中的底层 JSON 字符串($header$payload$token)也必须与 JavaScript 代码中的对应部分相同,否则签名会有所不同。由于 PHP 代码不完整,因此无法检查这可能是问题的另一个原因。

    【讨论】:

    • 我希望我能对这个答案投票超过 10 次。顺便说一句,php代码怎么不完整?
    • Incomplete 仅在发布的 sn-p 中缺少某些定义的意义上,例如ALG, TYP, getClientID(),... 因此,必须使用 $header$payloadsubstitute 定义,以便 original定义仍未得到检验。没什么大不了的。
    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2020-04-18
    • 2020-04-25
    • 2018-09-02
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    相关资源
    最近更新 更多