mirror of
https://github.com/danog/phpseclib.git
synced 2024-12-02 09:38:06 +01:00
add JSON Web Key (JWK) support
This commit is contained in:
parent
13b241e3e9
commit
0b3c6e27fc
@ -470,11 +470,11 @@ abstract class Strings
|
||||
*/
|
||||
public static function base64url_encode($data)
|
||||
{
|
||||
// return self::base64_encode(str_replace(['+', '/'], ['-', '_'], $data));
|
||||
// return str_replace(['+', '/'], ['-', '_'], self::base64_encode($data));
|
||||
|
||||
return function_exists('sodium_bin2base64') ?
|
||||
sodium_bin2base64($data, SODIUM_BASE64_VARIANT_URLSAFE) :
|
||||
Base64::encode($data);
|
||||
Base64UrlSafe::encode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
69
phpseclib/Crypt/Common/Formats/Keys/JWK.php
Normal file
69
phpseclib/Crypt/Common/Formats/Keys/JWK.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JSON Web Key (RFC7517) Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib3\Crypt\Common\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
|
||||
/**
|
||||
* JSON Web Key Formatted Key Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class JWK
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $password
|
||||
* @return array
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
if (!Strings::is_stringable($key)) {
|
||||
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||
}
|
||||
|
||||
$key = preg_replace('#\s#', '', $key); // remove whitespace
|
||||
|
||||
if (PHP_VERSION_ID >= 73000) {
|
||||
$key = json_decode($key, null, 512, JSON_THROW_ON_ERROR);
|
||||
} else {
|
||||
$key = json_decode($key);
|
||||
if (!$key) {
|
||||
throw new \RuntimeException('Unable to decode JSON');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($key->kty)) {
|
||||
return $key;
|
||||
}
|
||||
|
||||
if (count($key->keys) != 1) {
|
||||
throw new \RuntimeException('Although the JWK key format supports multiple keys phpseclib does not');
|
||||
}
|
||||
|
||||
return $key->keys[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a key appropriately
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function wrapKey(array $key, array $options)
|
||||
{
|
||||
return json_encode(['keys' => [$key + $options]]);
|
||||
}
|
||||
}
|
190
phpseclib/Crypt/EC/Formats/Keys/JWK.php
Normal file
190
phpseclib/Crypt/EC/Formats/Keys/JWK.php
Normal file
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JSON Web Key (RFC7517 / RFC8037) Formatted EC Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib3\Crypt\EC\Formats\Keys;
|
||||
|
||||
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor;
|
||||
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||
use phpseclib3\Crypt\EC\Curves\Ed25519;
|
||||
use phpseclib3\Crypt\EC\Curves\secp256r1;
|
||||
use phpseclib3\Crypt\EC\Curves\secp384r1;
|
||||
use phpseclib3\Crypt\EC\Curves\secp521r1;
|
||||
use phpseclib3\Crypt\EC\Curves\secp256k1;
|
||||
use phpseclib3\Exception\UnsupportedCurveException;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* JWK Formatted EC Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class JWK extends Progenitor
|
||||
{
|
||||
use Common;
|
||||
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $password optional
|
||||
* @return array
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
switch ($key->kty) {
|
||||
case 'EC':
|
||||
switch ($key->crv) {
|
||||
case 'P-256':
|
||||
case 'P-384':
|
||||
case 'P-521':
|
||||
case 'secp256k1':
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedCurveException('Only P-256, P-384, P-521 and secp256k1 curves are accepted (' . $key->crv . ' provided)');
|
||||
}
|
||||
break;
|
||||
case 'OKP':
|
||||
switch ($key->crv) {
|
||||
case 'Ed25519':
|
||||
case 'Ed448':
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedCurveException('Only Ed25519 and Ed448 curves are accepted (' . $key->crv . ' provided)');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Only EC and OKP JWK keys are supported');
|
||||
}
|
||||
|
||||
$curve = '\phpseclib3\Crypt\EC\Curves\\' . str_replace('P-', 'nistp', $key->crv);
|
||||
$curve = new $curve;
|
||||
|
||||
if ($curve instanceof TwistedEdwardsCurve) {
|
||||
$QA = self::extractPoint(Strings::base64url_decode($key->x), $curve);
|
||||
if (!isset($key->d)) {
|
||||
return compact('curve', 'QA');
|
||||
}
|
||||
$dA = $curve->extractSecret(Strings::base64url_decode($key->d));
|
||||
return compact('curve', 'dA', 'QA');
|
||||
}
|
||||
|
||||
$QA = [
|
||||
$curve->convertInteger(new BigInteger(Strings::base64url_decode($key->x), 256)),
|
||||
$curve->convertInteger(new BigInteger(Strings::base64url_decode($key->y), 256))
|
||||
];
|
||||
|
||||
if (!$curve->verifyPoint($QA)) {
|
||||
throw new \RuntimeException('Unable to verify that point exists on curve');
|
||||
}
|
||||
|
||||
if (!isset($key->d)) {
|
||||
return compact('curve', 'QA');
|
||||
}
|
||||
|
||||
$dA = new BigInteger(Strings::base64url_decode($key->d), 256);
|
||||
|
||||
$curve->rangeCheck($dA);
|
||||
|
||||
return compact('curve', 'dA', 'QA');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alias that corresponds to a curve
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getAlias(BaseCurve $curve)
|
||||
{
|
||||
switch (true) {
|
||||
case $curve instanceof secp256r1:
|
||||
return 'P-256';
|
||||
case $curve instanceof secp384r1:
|
||||
return 'P-384';
|
||||
case $curve instanceof secp521r1:
|
||||
return 'P-521';
|
||||
case $curve instanceof secp256k1:
|
||||
return 'secp256k1';
|
||||
}
|
||||
|
||||
$reflect = new \ReflectionClass($curve);
|
||||
$curveName = $reflect->isFinal() ?
|
||||
$reflect->getParentClass()->getShortName() :
|
||||
$reflect->getShortName();
|
||||
throw new UnsupportedCurveException("$curveName is not a supported curve");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array superstructure for an EC public key
|
||||
*
|
||||
* @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
|
||||
* @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @return array
|
||||
*/
|
||||
private static function savePublicKeyHelper(BaseCurve $curve, array $publicKey)
|
||||
{
|
||||
if ($curve instanceof TwistedEdwardsCurve) {
|
||||
return [
|
||||
'kty' => 'OKP',
|
||||
'crv' => $curve instanceof Ed25519 ? 'Ed25519' : 'Ed448',
|
||||
'x' => Strings::base64url_encode($curve->encodePoint($publicKey))
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'kty' => 'EC',
|
||||
'crv' => self::getAlias($curve),
|
||||
'x' => Strings::base64url_encode($publicKey[0]->toBytes()),
|
||||
'y' => Strings::base64url_encode($publicKey[1]->toBytes())
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an EC public key to the appropriate format
|
||||
*
|
||||
* @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
|
||||
* @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @param array $options optional
|
||||
* @return string
|
||||
*/
|
||||
public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
|
||||
{
|
||||
$key = self::savePublicKeyHelper($curve, $publicKey);
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*
|
||||
* @param \phpseclib3\Math\BigInteger $privateKey
|
||||
* @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
|
||||
* @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @param string $password optional
|
||||
* @param array $options optional
|
||||
* @return string
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
|
||||
{
|
||||
$key = self::savePublicKeyHelper($curve, $publicKey);
|
||||
$key['d'] = $curve instanceof TwistedEdwardsCurve ?
|
||||
$privateKey->secret :
|
||||
$privateKey->toBytes();
|
||||
$key['d'] = Strings::base64url_encode($key['d']);
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
}
|
142
phpseclib/Crypt/RSA/Formats/Keys/JWK.php
Normal file
142
phpseclib/Crypt/RSA/Formats/Keys/JWK.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JSON Web Key (RFC7517) Formatted RSA Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib3\Crypt\RSA\Formats\Keys;
|
||||
|
||||
use phpseclib3\Common\Functions\Strings;
|
||||
use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor;
|
||||
use phpseclib3\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* JWK Formatted RSA Handler
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
abstract class JWK extends Progenitor
|
||||
{
|
||||
/**
|
||||
* Break a public or private key down into its constituent components
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $password optional
|
||||
* @return array
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
$key = parent::load($key, $password);
|
||||
|
||||
if ($key->kty != 'RSA') {
|
||||
throw new \RuntimeException('Only RSA JWK keys are supported');
|
||||
}
|
||||
|
||||
$count = $publicCount = 0;
|
||||
$vars = ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi'];
|
||||
foreach ($vars as $var) {
|
||||
if (!isset($key->$var) || !is_string($key->$var)) {
|
||||
continue;
|
||||
}
|
||||
$count++;
|
||||
$value = new BigInteger(Strings::base64url_decode($key->$var), 256);
|
||||
switch ($var) {
|
||||
case 'n':
|
||||
$publicCount++;
|
||||
$components['modulus'] = $value;
|
||||
break;
|
||||
case 'e':
|
||||
$publicCount++;
|
||||
$components['publicExponent'] = $value;
|
||||
break;
|
||||
case 'd':
|
||||
$components['privateExponent'] = $value;
|
||||
break;
|
||||
case 'p':
|
||||
$components['primes'][1] = $value;
|
||||
break;
|
||||
case 'q':
|
||||
$components['primes'][2] = $value;
|
||||
break;
|
||||
case 'dp':
|
||||
$components['exponents'][1] = $value;
|
||||
break;
|
||||
case 'dq':
|
||||
$components['exponents'][2] = $value;
|
||||
break;
|
||||
case 'qi':
|
||||
$components['coefficients'][2] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($count == count($vars)) {
|
||||
return $components + ['isPublicKey' => false];
|
||||
}
|
||||
|
||||
if ($count == 2 && $publicCount == 2) {
|
||||
return $components + ['isPublicKey' => true];
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('Key does not have an appropriate number of RSA parameters');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a private key to the appropriate format.
|
||||
*
|
||||
* @param \phpseclib3\Math\BigInteger $n
|
||||
* @param \phpseclib3\Math\BigInteger $e
|
||||
* @param \phpseclib3\Math\BigInteger $d
|
||||
* @param array $primes
|
||||
* @param array $exponents
|
||||
* @param array $coefficients
|
||||
* @param string $password optional
|
||||
* @param array $options optional
|
||||
* @return string
|
||||
*/
|
||||
public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
|
||||
{
|
||||
if (count($primes) != 2) {
|
||||
throw new \InvalidArgumentException('JWK does not support multi-prime RSA keys');
|
||||
}
|
||||
|
||||
$key = [
|
||||
'kty' => 'RSA',
|
||||
'n' => Strings::base64url_encode($n->toBytes()),
|
||||
'e' => Strings::base64url_encode($e->toBytes()),
|
||||
'd' => Strings::base64url_encode($d->toBytes()),
|
||||
'p' => Strings::base64url_encode($primes[1]->toBytes()),
|
||||
'q' => Strings::base64url_encode($primes[2]->toBytes()),
|
||||
'dp' => Strings::base64url_encode($exponents[1]->toBytes()),
|
||||
'dq' => Strings::base64url_encode($exponents[2]->toBytes()),
|
||||
'qi' => Strings::base64url_encode($coefficients[2]->toBytes())
|
||||
];
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a public key to the appropriate format
|
||||
*
|
||||
* @param \phpseclib3\Math\BigInteger $n
|
||||
* @param \phpseclib3\Math\BigInteger $e
|
||||
* @param array $options optional
|
||||
* @return string
|
||||
*/
|
||||
public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
|
||||
{
|
||||
$key = [
|
||||
'kty' => 'RSA',
|
||||
'n' => Strings::base64url_encode($n->toBytes()),
|
||||
'e' => Strings::base64url_encode($e->toBytes())
|
||||
];
|
||||
|
||||
return self::wrapKey($key, $options);
|
||||
}
|
||||
}
|
@ -574,4 +574,96 @@ MIIEDwIBADATBgcqhkjOPQIBBggqhkjOPQMBBwSCA/MwggPvAgEBBIID6P//////
|
||||
$key = PublicKeyLoader::load($key, 'test');
|
||||
$this->assertInstanceOf(PrivateKey::class, $key);
|
||||
}
|
||||
|
||||
public function testECasJWK()
|
||||
{
|
||||
// keys are from https://datatracker.ietf.org/doc/html/rfc7517#appendix-A
|
||||
|
||||
$plaintext = 'zzz';
|
||||
|
||||
$key = ' {"keys":
|
||||
[
|
||||
{"kty":"EC",
|
||||
"crv":"P-256",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
|
||||
"use":"enc",
|
||||
"kid":"1"}
|
||||
]
|
||||
}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK', [
|
||||
'use' => 'enc',
|
||||
'kid' => '1'
|
||||
]));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$sig = $key->sign($plaintext);
|
||||
|
||||
$key = '{"keys":
|
||||
[
|
||||
{"kty":"EC",
|
||||
"crv":"P-256",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"use":"enc",
|
||||
"kid":"1"}
|
||||
]
|
||||
}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK', [
|
||||
'use' => 'enc',
|
||||
'kid' => '1'
|
||||
]));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$this->assertTrue($key->verify($plaintext, $sig));
|
||||
}
|
||||
|
||||
public function testEd25519asJWK()
|
||||
{
|
||||
// keys are from https://www.rfc-editor.org/rfc/rfc8037.html#appendix-A
|
||||
|
||||
$plaintext = 'zzz';
|
||||
|
||||
$key = ' {"kty":"OKP","crv":"Ed25519",
|
||||
"x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
|
||||
"d":"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A"}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
$keyWithoutWS = '{"keys":[' . $keyWithoutWS . ']}';
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK'));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$sig = $key->sign($plaintext);
|
||||
|
||||
$key = ' {"kty":"OKP","crv":"Ed25519",
|
||||
"x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
$keyWithoutWS = '{"keys":[' . $keyWithoutWS . ']}';
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK'));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$this->assertTrue($key->verify($plaintext, $sig));
|
||||
}
|
||||
}
|
||||
|
@ -1277,4 +1277,86 @@ LrIZULwMa4nI4Y+RkFftEponSYw=
|
||||
$key = PublicKeyLoader::load($key, 'test');
|
||||
$this->assertInstanceOf(PrivateKey::class, $key);
|
||||
}
|
||||
|
||||
public function testJWK()
|
||||
{
|
||||
// keys are from https://datatracker.ietf.org/doc/html/rfc7517#appendix-A
|
||||
|
||||
$plaintext = 'zzz';
|
||||
|
||||
$key = ' {"keys":
|
||||
[
|
||||
{"kty":"RSA",
|
||||
"n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4
|
||||
cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMst
|
||||
n64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2Q
|
||||
vzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbIS
|
||||
D08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw
|
||||
0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"e":"AQAB",
|
||||
"d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9
|
||||
M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij
|
||||
wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d
|
||||
_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz
|
||||
nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz
|
||||
me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
|
||||
"p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV
|
||||
nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV
|
||||
WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
|
||||
"q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum
|
||||
qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx
|
||||
kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
|
||||
"dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim
|
||||
YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu
|
||||
YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
|
||||
"dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU
|
||||
vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9
|
||||
GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
|
||||
"qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg
|
||||
UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx
|
||||
yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
|
||||
"alg":"RS256",
|
||||
"kid":"2011-04-29"}
|
||||
]
|
||||
}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK', [
|
||||
'alg' => 'RS256',
|
||||
'kid' => '2011-04-29'
|
||||
]));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$sig = $key->sign($plaintext);
|
||||
|
||||
$key = ' {"kty":"RSA",
|
||||
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
|
||||
4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
|
||||
tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
|
||||
QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
|
||||
SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
|
||||
w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"e":"AQAB",
|
||||
"alg":"RS256",
|
||||
|
||||
"kid":"2011-04-29"}';
|
||||
|
||||
$keyWithoutWS = preg_replace('#\s#', '', $key);
|
||||
$keyWithoutWS = '{"keys":[' . $keyWithoutWS . ']}';
|
||||
|
||||
$key = PublicKeyLoader::load($key);
|
||||
|
||||
$phpseclibKey = str_replace('=', '', $key->toString('JWK', [
|
||||
'alg' => 'RS256',
|
||||
'kid' => '2011-04-29'
|
||||
]));
|
||||
|
||||
$this->assertSame($keyWithoutWS, $phpseclibKey);
|
||||
|
||||
$this->assertTrue($key->verify($plaintext, $sig));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user