Skip to content

Commit

Permalink
✨ 新增支持RS256,优化verify signature 方法
Browse files Browse the repository at this point in the history
  • Loading branch information
RunsTp committed Feb 23, 2021
1 parent 4b71a75 commit 96865be
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 24 deletions.
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
],
"require": {
"php": ">=7.1.0",
"ext-json": "*",
"ext-openssl": ">=1.0.0",
"easyswoole/spl": "^1.2",
"easyswoole/component": "^2.0",
"easyswoole/utility": "^1.1"
},
"require-dev": {
Expand All @@ -27,7 +29,7 @@
},
"autoload-dev": {
"psr-4": {
"EasySwoole\\Jwt\\Tests\\": "test/"
"EasySwoole\\Jwt\\Tests\\": "tests/"
}
}
}
1 change: 1 addition & 0 deletions src/Jwt.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Jwt
public const ALG_METHOD_AES = 'AES';
public const ALG_METHOD_HMACSHA256 = 'HMACSHA256';
public const ALG_METHOD_HS256 = 'HS256';
public const ALG_METHOD_RS256 = 'RS256';

public static function getInstance():Jwt
{
Expand Down
65 changes: 49 additions & 16 deletions src/JwtObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace EasySwoole\Jwt;

use DomainException;
use EasySwoole\Spl\SplBean;
use EasySwoole\Utility\Random;
use UnexpectedValueException;

class JwtObject extends SplBean
{
Expand All @@ -28,41 +30,72 @@ class JwtObject extends SplBean
protected $header;
protected $payload;

protected $algMap = [
Jwt::ALG_METHOD_AES => 'AES-128-ECB',
Jwt::ALG_METHOD_RS256 => 'SHA256'
];

protected function initialize(): void
{
if(empty($this->nbf)){
if (empty($this->nbf)) {
$this->nbf = time();
}
if(empty($this->iat)){
if (empty($this->iat)) {
$this->iat = time();
}
if(empty($this->exp)){
if (empty($this->exp)) {
$this->exp = time() + 7200;
}
if(empty($this->jti)){
if (empty($this->jti)) {
$this->jti = Random::character(10);
}

// 解包:验证签名
if(!empty($this->signature)){
$signature = (new Signature([
'secretKey' => $this->getSecretKey(),
'header' => $this->getHeader(),
'payload' => $this->getPayload(),
'alg' => $this->getAlg()
]))->__toString();
if($this->signature !== $signature){
if (!empty($this->signature)) {
// $signature = (new Signature([
// 'secretKey' => $this->getSecretKey(),
// 'header' => $this->getHeader(),
// 'payload' => $this->getPayload(),
// 'alg' => $this->getAlg()
// ]))->__toString();
if (false === $this->verify()) {
$this->status = self::STATUS_SIGNATURE_ERROR;
return;
}
if(time() > $this->exp){
if (time() > $this->exp) {
$this->status = self::STATUS_EXPIRED;
return;
}
}
$this->status = self::STATUS_OK;
}

/**
* @return bool
*/
protected function verify(): bool
{
$content = $this->getHeader() . "." . $this->getPayload();

if (in_array($this->getAlg(), [Jwt::ALG_METHOD_HMACSHA256, Jwt::ALG_METHOD_HS256])) {
$hash = hash_hmac('SHA256', $content, $this->getSecretKey(), true);
return hash_equals($this->getSignature(), Encryption::getInstance()->base64UrlEncode($hash));
}

if (in_array($this->getAlg(), [Jwt::ALG_METHOD_AES, Jwt::ALG_METHOD_RS256])) {
$signatureAlg = $this->algMap[$this->getAlg()] ?? null;
if (!empty($signatureAlg)) {
$status = openssl_verify($content, Encryption::getInstance()->base64UrlDecode($this->getSignature()), $this->getSecretKey(), $signatureAlg);
if ($status < 0) {
throw new DomainException('OpenSSL error: ' . openssl_error_string());
}
return $status === 1;
}
}

throw new UnexpectedValueException('Algorithm not supported, alg: ' . $this->getAlg());
}

/**
* @return mixed
*/
Expand Down Expand Up @@ -279,8 +312,8 @@ public function getHeader()

public function setPayload($payload)
{
$this->payload = $payload;
return $this;
$this->payload = $payload;
return $this;
}

public function getPayload()
Expand Down Expand Up @@ -313,7 +346,7 @@ public function __toString()
'iss' => $this->getIss(),
'status' => $this->getStatus(),
'data' => $this->getData()
], JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$this->payload = Encryption::getInstance()->base64UrlEncode($payload);

$this->signature = (new Signature([
Expand Down
20 changes: 13 additions & 7 deletions src/Signature.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* @Copyright: copyright(2020) Easyswoole all rights reserved
* @Description: 签名生成
*/

namespace EasySwoole\Jwt;

use EasySwoole\Component\Singleton;
use EasySwoole\Spl\SplBean;

class Signature extends SplBean
Expand All @@ -22,12 +22,9 @@ public function __toString()
{
$content = $this->header . '.' . $this->payload;

switch ($this->alg){
$signature = "";
switch ($this->alg) {
case Jwt::ALG_METHOD_HMACSHA256:
$signature = Encryption::getInstance()->base64UrlEncode(
hash_hmac('sha256', $content, $this->secretKey, true)
);
break;
case Jwt::ALG_METHOD_HS256:
$signature = Encryption::getInstance()->base64UrlEncode(
hash_hmac('sha256', $content, $this->secretKey, true)
Expand All @@ -38,8 +35,17 @@ public function __toString()
openssl_encrypt($content, 'AES-128-ECB', $this->secretKey)
);
break;
case Jwt::ALG_METHOD_RS256:
$success = openssl_sign($content, $signature, $this->secretKey, 'SHA256');
if (!$success) {
$signature = "";
}
break;
default:
throw new UnexpectedValueException('Alg is invalid!');
/**
* php 7.4以下不支持在__toString()抛出异常
*/
$signature = "";
}

return $signature;
Expand Down

0 comments on commit 96865be

Please sign in to comment.