itaiarbel / jwt
JWT、JWS、JWE 库
Requires
- lib-openssl: *
This package is not auto-updated.
Last update: 2024-09-30 10:48:27 UTC
README
易于使用、轻量级、用户友好的 JWT 库 ** 无依赖 ** - 所有算法仅使用 PHP OpenSSL 实现。
免责声明
2020年8月22日 - BETA - 所有功能似乎都正常工作,
未完全测试安全性 / 未完全符合 RFC 标准。自行承担风险!
欢迎使用此库,并通过发现错误和实现缺失算法来帮助我改进它。
它能做什么?
- JWS - HS256 - 签名/验证 - 使用共享密钥
- JWS - HS384 - 签名/验证 - 使用共享密钥
- JWS - HS512 - 签名/验证 - 使用共享密钥
- JWS - RS256 - 签名/验证 - 使用私钥和公钥
- JWS - RS384 - 签名/验证 - 使用私钥和公钥
- JWS - RS512 - 签名/验证 - 使用私钥和公钥
- JWE - RSA1_5 + A128CBC-HS256 - 加密/解密 - 使用私钥和公钥
- JWE - RSA1_5 + A192CBC-HS384 - 加密/解密 - 使用私钥和公钥
- JWE - RSA1_5 + A256CBC-HS512 - 加密/解密 - 使用私钥和公钥
- JWE - RSA1_5 + A128GCM - 加密/解密 - 使用私钥和公钥
- JWE - RSA1_5 + A192GCM - 加密/解密 - 使用私钥和公钥
- JWE - RSA1_5 + A256GCM - 加密/解密 - 使用私钥和公钥
目录
安装
运行以下 composer 命令
composer require itaiarbel/jwt
然后在您的项目中使用它
use Itaiarbel\Jwt\Jwt;
构建器
允许您构建 JWT,然后对其进行签名/加密。
使用示例
$jws= Jwt::Builder()
->jti()
->claim('iss','me')
->claim('aud','you')
->exp(3600)
->claim('sub','123123')
->sign('SuPerSeCrEtKeY','HS256');
echo $jws->jwt; //your jws string
$private_rsa_key='
-----BEGIN PRIVATE KEY-----
... generate your own 2048bit/4096bit RSA keys ...
-----END PRIVATE KEY-----';
$public_rsa_key='
-----BEGIN PUBLIC KEY-----
... generate your own 2048bit/4096bit RSA keys ...
-----END PUBLIC KEY-----';
$jws2= Jwt::Builder()
->header('kid','38890') //optional key id - for key menegment
->jti()
->claim('iss','me')
->claim('aud','you')
->exp(3600)
->nbf(600)
->claim('sub','123123')
->claim('user_verified','1')
->sign($private_rsa_key,'RS256');
echo $jws2->jwt; //your jws signed string using the private key
$private_rsa_key='
-----BEGIN PRIVATE KEY-----
... generate your own 2048bit/4096bit RSA keys ...
-----END PRIVATE KEY-----';
$jwe= Jwt::Builder()
->header('kid','1')
->jti()
->claim('iss','me')
->claim('aud','you')
->exp(3600)
->nbf(600)
->claim('sub','123123')
->claim('user_verified','1')
->encrypt($private_rsa_key,'RSA1_5','A128CBC-HS256');
echo $jwe->jwt; //your jwe string encrypted using the private key
##构建器方法
claim(key, val) / claims([key=>val,key=>val...]) : 向令牌的有效负载部分添加声明/声明
->claim('first_name','john') //add claim
->claim('last_name','doe') // one by one
->claims([ //or add multiple claims as array
'first_name'=>'john',
'last_name'=>'doe'
])
->claim('user',[ //adds json object claim under 'user'
'user_id' => '123',
'first_name'=>'john',
'last_name'=>'doe'
]);
header(key, val) : 向令牌的标头部分添加声明(注意:JWE 中的标头声明不被加密)
->header('kid','123') //set key id
exp(secs,server_ts[opt]) : 添加 'exp' 令牌过期时间声明为 time()+secs,您可以为不同的时区设置服务器时间戳。
->exp(3600) //time()+3600
->exp(3600,$ts) // $ts + 3600
nfb(secs) : 添加 'nbf' 令牌未生效之前声明为 time()+secs
->nbf(600) //time()+600
->nbf(600,$ts) //$ts+600
jti(val[opt]) : 添加 'jti' 令牌 ID 声明,如果没有提供参数,则为自动生成的随机 GUID
->jti() //e.g b1e029d4-c452-4ab4-9c0a-39db17896224
->jti('random-id-123-123') //or use your own id
->claim('jti','random-id-123-123') //you can use claim function instead
iss(val)/issuer(val) : 添加 'iss' 令牌发行者声明
->iss('me')
->issuer('me') //or
->claim('iss','me') //or
sign(key, alg) : 完成构建器并签名 JWT。 - > JWS
->sign('SuPerSeCrEtKeY','HS512'); //sign with HMAC-SHA512 using a secret key
->sign($private_key_pem,'RS512'); //sign with RSA-SHA512 using a private key
encrypt(key, alg, enc) : 完成构建器并加密 JWT。 -> JWE
->encrypt($private_key_pem,'RSA1_5','A256CBC-HS512'); //encrypt using RSA & AES256CBC-HS512
->encrypt($private_key_pem,'RSA1_5','A256GCM'); //encrypt using RSA & AES128GCM
检查器
使用示例
JWS 验证
//this is a 5y valid token signed with HS256 with key 'SuPerSeCrEtKeY'
$jws_string="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyM2YxYmY5Ny02NTlkLTQ2MjAtOWY1Ni0yOGVjMWUxN2MyYmQiLCJpc3MiOiJtZSIsImF1ZCI6InlvdSIsImlhdCI6MTU5ODExMjQ3NSwiZXhwIjoxNzU1NzkyNDc1LCJzdWIiOiIxMjMxMjMifQ.JSIWCGxG8ay-h3LKoZ9pCd5sx4cqK-Wqn2pKtJoBAn4";
try{
$jws= Jwt::Checker($jws_string)->verify('SuPerSeCrEtKeY','HS256');
}catch(Exception $e){
//exception will happen if the input is not valid jwt
$jws=false;
echo "INVALID TOKEN INPUT!<br>";
}
if ($jws && $jws->validate()){ //validates exp & nbf & signiture here
echo "VALID TOKEN!!<br>";
print_r($jws->getClaims()); //print all claims
echo '<br><br>';
}else{
echo "TOKEN NOT VALID!!<br>";
}
//same as above + checking extra fields like issuer
if (
$jws && //ckeck input of token
$jws->verified && // Signature verification
$jws->checkExp() && //If exp timstamp passed
$jws->checkNbf() && //checkNbf
//up to here - same as calling: $jws->validate()
$jws->iss('me') && //If issuer is"me"
$jws->aud('you') //If audience is "you"
){
echo "VALID TOKEN FROM ME TO YOU!!<br>";
print_r($jws->getClaims()); //print all claims
echo '<br><br>';
}else{
echo "TOKEN NOT VALID!!<br>";
}
JWE 解密
$public_rsa_key='
-----BEGIN PUBLIC KEY-----
... generate your own 2048bit/4096bit RSA keys ...
-----END PUBLIC KEY-----';
try{
//start checker with jwt string input
$jwe= Jwt::Checker($user_input_jwe);
//you can get header claims before decrypting like: alg,enc,kid ect...
$header= $jwe->getHeaderClaims();
//$jwe->decrypt($public_key,$header['alg'],$header['enc']); //extract alg &enc from header
$jwe->decrypt($public_rsa_key,'RSA1_5','A128CBC-HS256');// or you can decrypt using known preset alg & enc
}catch(Exception $e){ //error decrypting/parsing
$jwe=false;
}
if ($jwe && $jwe->validate()){ //validates exp & nbf & decryption here
echo "VALID TOKEN!!<br>";
print_r($jwe->getClaims()); //print all claims
echo '<br><br>';
}else{
echo "TOKEN NOT VALID!!<br>";
}
//same as above + checking extra fields like issuer
if (
$jwe && //ckeck input of token
$jwe->decrypted && // Signature verification
$jwe->checkExp() && //If exp timstamp passed
$jwe->checkNbf() && //checkNbf
//up to here - same as calling: $jws->validate()
$jwe->iss('me') && //If issuer is"me"
$jwe->aud('you') //If audience is "you"
){
echo "VALID TOKEN FROM ME TO YOU!!<br>";
print_r($jwe->getClaims()); //print all claims
echo '<br><br>';
}else{
echo "TOKEN NOT VALID!!<br>";
}
注意:已验证并不表示有效令牌,它仅检查签名,不检查令牌时间的有效性,您必须自行检查过期时间戳/nbf/iss 黑名单/捕获/数据库等...
##检查器方法
verify(key/secret,alg) - 使用公钥/密钥验证 JWS
$jws->verify($public_key_pem,'RS512');
$jws->verify('secretkey','HS512');
decrypt(key/secret,alg,enc) - 使用公钥解密 JWE
$jwe->decrypt($public_key_pem,'RSA1_5','A256CBC-HS512');
getHeaderClaims():array - 获取 JWE/JWS 中所有标头声明的数组
$jws->getHeaderClaims();
getHeaderClaim(name):string - 从标头获取特定声明
$jws->getHeaderClaim('kid');
hasHeaderClaim(name):bool - 如果标头声明存在,则返回 true/false
if($jws->hasHeaderClaim('kid')){
$key= your_own_get_key_by_id(
$jws->kid()
);
}
kid()/keyId():string - 从标头获取 'kid' 声明
$kid= $jwe->kid();
$kid= $jwe->keyId();
alg()/algorithm():string - 从标头获取 'alg' 声明
$alg = $jws->alg();
$alg = $jws->algorithm();
enc()/encryption():string - 从标头获取 'enc' 声明
$enc = $jwe->enc();
$enc = $jwe->encryption();
validate(server_ts[opt]):bool - 验证签名/解密 + exp + nbf
if ($jwe && $jwe->validate()){
echo 'Token is valid and not expiered';
}
checkExp(ts[opt]):bool - 如果 exp 声明时间已过,则返回 true/false
if (!$jwe->checkExp()){
echo 'Token is expiered';
}
checkNbf(ts[opt]):bool - 如果 nbf 时间不是在现在之前,则返回 true/false。注意:如果 nbf 声明不存在 - 返回 true,因为此声明是可选的
if (!$jwe->checkNbf()){
echo 'Used Token too soon';
}
checkClaim(name,expected_val):bool - 返回 true/false - 检查声明与预期值是否匹配
if ($jwe->checkClaim('user_verified','1')){
echo 'User is Verified!';
}
checkHeaderClaim(name,expected_val):bool - 返回 true/false - 检查头部声明与预期值是否匹配
if ($jwe->checkHeaderClaim('kid','12')){
echo 'token is using key #12';
}
getClaims():array - 获取所有声明的数组(如果令牌尚未解密,将返回空数组)
print_r($jws->getClaims());
getClaim(name):string - 通过名称获取特定声明(如果令牌尚未解密,将返回空字符串)
$username = $jws->getClaim('username');
hasClaim(name):bool - 如果声明存在则返回 true/false(如果令牌尚未解密,则返回 false)
if($jws->hasClaim('username')){
{
echo 'hello '.$jws->getClaim('username');
}
iss()/issuer():string - 获取发行者 'iss' 声明
$jws->iss();
$jws->issuer();
sub()/subject():string - 获取主题 'sub' 声明
$user_id = $jws->sub();
$user_id = $jws->subject();
aud()/audience():string - 获取受众 'aud' 声明
$jws->aud();
$jws->audience();
exp()/expires():string - 获取过期时间 'exp' 声明
$jws->exp();
$jws->expires();
nbf()/notBefore():string - 获取不早于时间 'nbf' 声明
$jws->nbf();
$jws->notBefore();
iat()/issuedAt():string - 获取发行时间 'iat' 声明
$jws->iat();
$jws->issuedAt();
jti()/id():string - 获取令牌 ID 'jti' 声明
$jws->jti();
$jws->id();
算法
实现的算法
- HS256 - HMAC-SHA256 - 签名/验证
- HS384 - HMAC-SHA384 - 签名/验证
- HS512 - HMAC-SHA512 - 签名/验证
- RS256 - RSA-PKCS1-SHA256 - 签名/验证
- RS384 - RSA-PKCS1-SHA384 - 签名/验证
- RS512 - RSA-PKCS1-SHA512 - 签名/验证
- RSA1_5 - 加密密钥/解密密钥
- A128CBC_HS256 - AES-128-CBC SHA256 - 加密/解密
- A192CBC_HS384 - AES-192-CBC SHA384 - 加密/解密
- A256CBC_HS512 - AES-256-CBC SHA512 - 加密/解密
- A128GCM - AES-128-GCM - 加密/解密
- A192GCM - AES-192-GCM - 加密/解密
- A256GCM - AES-256-GCM - 加密/解密
待办事项:算法 TODO:(也许你可以帮忙?)
- dir
- PS256
- PS384
- PS512
- ES256
- ES384
- ES512
- RSA-OAEP
- RSA-OAEP-256
- A128KW
- A192KW
- A256KW
- ECDH-ES
- ECDH-ES+A128KW
- ECDH-ES+A192KW
- ECDH-ES+A256KW
- A128GCMKW
- A192GCMKW
- A256GCMKW
- PBES2-HS256+A128KW
- PBES2-HS384+A192KW
- PBES2-HS512+A256KW
贡献
贡献方式
- 添加算法
- 查找错误
- 修复错误
- 改进现有代码
支持
- 给我买一杯咖啡
联系
您可以通过itai@arbelis.com联系我