我正在使用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中找到的所有库中,它们仅在sha256
函数中内部传递openssl_sign
。而且openssl_sign
没有使用RS256作为算法参数。
所以,首先,在哪里我出了错。
第二,有没有一种方法可以使用php中的RS256生成签名。
PS:我正在寻找php中的解决方案。
答案 0 :(得分:2)
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编码(RFC4648, sect. 5),而PHP(或更准确地说是base64_encode
方法)使用 standard Base64编码(RFC4648, sect. 4),这很可能是造成此问题的原因之一。这意味着当前PHP代码中的编码必须更改为Base64url,例如here。
当然,PHP代码中的基础JSON字符串($header
,$payload
和$token
)也必须与JavaScript代码中的JSON字符串相同。 ,否则签名会有所不同。由于PHP代码不完整,因此无法检查,并且可能是导致此问题的另一原因。