From ec635dc40e15c10fa76a9288bed540edccc87011 Mon Sep 17 00:00:00 2001 From: Spomky Date: Tue, 29 May 2018 13:24:47 +0200 Subject: [PATCH] Sub-packages for algorithms --- .github/CONTRIBUTING.md | 4 + .github/PULL_REQUEST_TEMPLATE.md | 3 + ECDHES.php | 390 +++++++++++++++++++++++++++++++ ECDHESA128KW.php | 43 ++++ ECDHESA192KW.php | 43 ++++ ECDHESA256KW.php | 43 ++++ ECDHESAESKW.php | 69 ++++++ LICENSE | 21 ++ README.md | 15 ++ Tests/ECDHESKeyAgreementTest.php | 245 +++++++++++++++++++ composer.json | 36 +++ phpunit.xml.dist | 29 +++ 12 files changed, 941 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 ECDHES.php create mode 100644 ECDHESA128KW.php create mode 100644 ECDHESA192KW.php create mode 100644 ECDHESA256KW.php create mode 100644 ECDHESAESKW.php create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Tests/ECDHESKeyAgreementTest.php create mode 100644 composer.json create mode 100644 phpunit.xml.dist diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..fc360e5 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contributing + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. +Please do not submit any Pull Requests here. It will be automatically closed. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..d4ff96c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Please do not submit any Pull Requests here. It will be automatically closed. + +You should submit it here: https://github.com/web-token/jwt-framework/pulls diff --git a/ECDHES.php b/ECDHES.php new file mode 100644 index 0000000..eddcaa3 --- /dev/null +++ b/ECDHES.php @@ -0,0 +1,390 @@ +has('d')) { + list($public_key, $private_key) = $this->getKeysFromPrivateKeyAndHeader($recipient_key, $complete_header); + } else { + list($public_key, $private_key) = $this->getKeysFromPublicKey($recipient_key, $additional_header_values); + } + + $agreed_key = $this->calculateAgreementKey($private_key, $public_key); + + $apu = array_key_exists('apu', $complete_header) ? $complete_header['apu'] : ''; + $apv = array_key_exists('apv', $complete_header) ? $complete_header['apv'] : ''; + + return ConcatKDF::generate($agreed_key, $algorithm, $encryption_key_length, $apu, $apv); + } + + /** + * @param JWK $recipient_key + * @param array $additional_header_values + * + * @return JWK[] + */ + private function getKeysFromPublicKey(JWK $recipient_key, array &$additional_header_values): array + { + $this->checkKey($recipient_key, false); + $public_key = $recipient_key; + switch ($public_key->get('crv')) { + case 'P-256': + case 'P-384': + case 'P-521': + $private_key = $this->createECKey($public_key->get('crv')); + + break; + case 'X25519': + $private_key = $this->createOKPKey('X25519'); + + break; + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported', $public_key->get('crv'))); + } + $epk = $private_key->toPublic()->all(); + $additional_header_values['epk'] = $epk; + + return [$public_key, $private_key]; + } + + /** + * @param JWK $recipient_key + * @param array $complete_header + * + * @return JWK[] + */ + private function getKeysFromPrivateKeyAndHeader(JWK $recipient_key, array $complete_header): array + { + $this->checkKey($recipient_key, true); + $private_key = $recipient_key; + $public_key = $this->getPublicKey($complete_header); + if ($private_key->get('crv') !== $public_key->get('crv')) { + throw new \InvalidArgumentException('Curves are different'); + } + + return [$public_key, $private_key]; + } + + /** + * @param JWK $private_key + * @param JWK $public_key + * + * @throws \InvalidArgumentException + * + * @return string + */ + public function calculateAgreementKey(JWK $private_key, JWK $public_key): string + { + switch ($public_key->get('crv')) { + case 'P-256': + case 'P-384': + case 'P-521': + $curve = $this->getCurve($public_key->get('crv')); + + $rec_x = $this->convertBase64ToGmp($public_key->get('x')); + $rec_y = $this->convertBase64ToGmp($public_key->get('y')); + $sen_d = $this->convertBase64ToGmp($private_key->get('d')); + + $priv_key = PrivateKey::create($sen_d); + $pub_key = $curve->getPublicKeyFrom($rec_x, $rec_y); + + return $this->convertDecToBin(EcDH::computeSharedKey($curve, $pub_key, $priv_key)); + case 'X25519': + $sKey = Base64Url::decode($private_key->get('d')); + $recipientPublickey = Base64Url::decode($public_key->get('x')); + + return sodium_crypto_scalarmult($sKey, $recipientPublickey); + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported', $public_key->get('crv'))); + } + } + + /** + * {@inheritdoc} + */ + public function name(): string + { + return 'ECDH-ES'; + } + + /** + * {@inheritdoc} + */ + public function getKeyManagementMode(): string + { + return self::MODE_AGREEMENT; + } + + /** + * @param array $complete_header + * + * @return JWK + */ + private function getPublicKey(array $complete_header) + { + if (!array_key_exists('epk', $complete_header)) { + throw new \InvalidArgumentException('The header parameter "epk" is missing'); + } + if (!is_array($complete_header['epk'])) { + throw new \InvalidArgumentException('The header parameter "epk" is not an array of parameter'); + } + + $public_key = JWK::create($complete_header['epk']); + $this->checkKey($public_key, false); + + return $public_key; + } + + /** + * @param JWK $key + * @param bool $is_private + */ + private function checkKey(JWK $key, $is_private) + { + if (!in_array($key->get('kty'), $this->allowedKeyTypes())) { + throw new \InvalidArgumentException('Wrong key type.'); + } + foreach (['x', 'crv'] as $k) { + if (!$key->has($k)) { + throw new \InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k)); + } + } + + switch ($key->get('crv')) { + case 'P-256': + case 'P-384': + case 'P-521': + if (!$key->has('y')) { + throw new \InvalidArgumentException('The key parameter "y" is missing.'); + } + + break; + case 'X25519': + break; + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported', $key->get('crv'))); + } + if (true === $is_private) { + if (!$key->has('d')) { + throw new \InvalidArgumentException('The key parameter "d" is missing.'); + } + } + } + + /** + * @param string $crv + * + * @throws \InvalidArgumentException + * + * @return Curve + */ + private function getCurve(string $crv): Curve + { + switch ($crv) { + case 'P-256': + return NistCurve::curve256(); + case 'P-384': + return NistCurve::curve384(); + case 'P-521': + return NistCurve::curve521(); + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported', $crv)); + } + } + + /** + * @param string $value + * + * @return \GMP + */ + private function convertBase64ToGmp(string $value): \GMP + { + $value = unpack('H*', Base64Url::decode($value)); + + return gmp_init($value[1], 16); + } + + /** + * @param \GMP $dec + * + * @return string + */ + private function convertDecToBin(\GMP $dec): string + { + if (gmp_cmp($dec, 0) < 0) { + throw new \InvalidArgumentException('Unable to convert negative integer to string'); + } + + $hex = gmp_strval($dec, 16); + + if (0 !== mb_strlen($hex, '8bit') % 2) { + $hex = '0'.$hex; + } + + return hex2bin($hex); + } + + /** + * @param string $crv The curve + * + * @return JWK + */ + public function createECKey(string $crv): JWK + { + try { + $jwk = self::createECKeyUsingOpenSSL($crv); + } catch (\Exception $e) { + $jwk = self::createECKeyUsingPurePhp($crv); + } + + return JWK::create($jwk); + } + + /** + * @param string $curve The curve + * + * @return JWK + */ + public static function createOKPKey(string $curve): JWK + { + switch ($curve) { + case 'X25519': + $keyPair = sodium_crypto_box_keypair(); + $d = sodium_crypto_box_secretkey($keyPair); + $x = sodium_crypto_box_publickey($keyPair); + + break; + case 'Ed25519': + $keyPair = sodium_crypto_sign_keypair(); + $d = sodium_crypto_sign_secretkey($keyPair); + $x = sodium_crypto_sign_publickey($keyPair); + + break; + default: + throw new \InvalidArgumentException(sprintf('Unsupported "%s" curve', $curve)); + } + + return JWK::create([ + 'kty' => 'OKP', + 'crv' => $curve, + 'x' => Base64Url::encode($x), + 'd' => Base64Url::encode($d), + ]); + } + + /** + * @param string $curve + * + * @return array + */ + private static function createECKeyUsingPurePhp(string $curve): array + { + switch ($curve) { + case 'P-256': + $nistCurve = NistCurve::curve256(); + + break; + case 'P-384': + $nistCurve = NistCurve::curve384(); + + break; + case 'P-521': + $nistCurve = NistCurve::curve521(); + + break; + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); + } + + $privateKey = $nistCurve->createPrivateKey(); + $publicKey = $nistCurve->createPublicKey($privateKey); + + return [ + 'kty' => 'EC', + 'crv' => $curve, + 'd' => Base64Url::encode(gmp_export($privateKey->getSecret())), + 'x' => Base64Url::encode(gmp_export($publicKey->getPoint()->getX())), + 'y' => Base64Url::encode(gmp_export($publicKey->getPoint()->getY())), + ]; + } + + /** + * @param string $curve + * + * @return array + */ + private static function createECKeyUsingOpenSSL(string $curve): array + { + $key = openssl_pkey_new([ + 'curve_name' => self::getOpensslCurveName($curve), + 'private_key_type' => OPENSSL_KEYTYPE_EC, + ]); + $res = openssl_pkey_export($key, $out); + if (false === $res) { + throw new \RuntimeException('Unable to create the key'); + } + $res = openssl_pkey_get_private($out); + + $details = openssl_pkey_get_details($res); + + return [ + 'kty' => 'EC', + 'crv' => $curve, + 'd' => Base64Url::encode($details['ec']['d']), + 'x' => Base64Url::encode($details['ec']['x']), + 'y' => Base64Url::encode($details['ec']['y']), + ]; + } + + /** + * @param string $curve + * + * @return string + */ + private static function getOpensslCurveName(string $curve): string + { + switch ($curve) { + case 'P-256': + return 'prime256v1'; + case 'P-384': + return 'secp384r1'; + case 'P-521': + return 'secp521r1'; + default: + throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); + } + } +} diff --git a/ECDHESA128KW.php b/ECDHESA128KW.php new file mode 100644 index 0000000..6f698ad --- /dev/null +++ b/ECDHESA128KW.php @@ -0,0 +1,43 @@ +getAgreementKey($this->getKeyLength(), $this->name(), $receiver_key->toPublic(), $complete_header, $additional_header_values); + $wrapper = $this->getWrapper(); + + return $wrapper::wrap($agreement_key, $cek); + } + + /** + * {@inheritdoc} + */ + public function unwrapAgreementKey(JWK $receiver_key, string $encrypted_cek, int $encryption_key_length, array $complete_header): string + { + $ecdh_es = new ECDHES(); + $agreement_key = $ecdh_es->getAgreementKey($this->getKeyLength(), $this->name(), $receiver_key, $complete_header); + $wrapper = $this->getWrapper(); + + return $wrapper::unwrap($agreement_key, $encrypted_cek); + } + + /** + * {@inheritdoc} + */ + public function getKeyManagementMode(): string + { + return self::MODE_WRAP; + } + + /** + * @return \AESKW\A128KW|\AESKW\A192KW|\AESKW\A256KW + */ + abstract protected function getWrapper(); + + /** + * @return int + */ + abstract protected function getKeyLength(): int; +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a098645 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2018 Spomky-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca3b813 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +ECDH-ES Based Key Encryption Algorithms For JWT-Framework +========================================================= + +This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY. + +**Please do not submit any Pull Request here.** +You should go to [the main repository](https://github.com/web-token/jwt-framework) instead. + +# Documentation + +The official documentation is available as https://web-token.spomky-labs.com/ + +# Licence + +This software is release under [MIT licence](LICENSE). diff --git a/Tests/ECDHESKeyAgreementTest.php b/Tests/ECDHESKeyAgreementTest.php new file mode 100644 index 0000000..4491c09 --- /dev/null +++ b/Tests/ECDHESKeyAgreementTest.php @@ -0,0 +1,245 @@ + 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + ]); + + $header = [ + 'enc' => 'A128GCM', + 'apu' => 'QWxpY2U', + 'apv' => 'Qm9i', + ]; + $ecdh_es = new ECDHES(); + $additional_header_values = []; + + $ecdh_es->getAgreementKey(128, 'A128GCM', $receiver, $header, $additional_header_values); + self::assertTrue(array_key_exists('epk', $additional_header_values)); + self::assertTrue(array_key_exists('kty', $additional_header_values['epk'])); + self::assertTrue(array_key_exists('crv', $additional_header_values['epk'])); + self::assertTrue(array_key_exists('x', $additional_header_values['epk'])); + self::assertTrue(array_key_exists('y', $additional_header_values['epk'])); + } + + public function testGetAgreementKeyWithA128KeyWrap() + { + $header = ['enc' => 'A128GCM']; + + $public = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + ]); + + $private = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + 'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw', + ]); + + $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]; + foreach ($cek as $key => $value) { + $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); + } + $cek = hex2bin(implode('', $cek)); + + $ecdh_es = new ECDHESA128KW(); + $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 128, $header, $header); + self::assertTrue(array_key_exists('epk', $header)); + self::assertTrue(array_key_exists('crv', $header['epk'])); + self::assertTrue(array_key_exists('kty', $header['epk'])); + self::assertTrue(array_key_exists('x', $header['epk'])); + self::assertTrue(array_key_exists('y', $header['epk'])); + self::assertEquals('P-256', $header['epk']['crv']); + self::assertEquals('EC', $header['epk']['kty']); + self::assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 128, $header)); + } + + public function testGetAgreementKeyWithA192KeyWrap() + { + $header = ['enc' => 'A192GCM']; + + $public = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + ]); + + $private = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + 'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw', + ]); + + $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]; + foreach ($cek as $key => $value) { + $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); + } + $cek = hex2bin(implode('', $cek)); + + $ecdh_es = new ECDHESA192KW(); + $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 192, $header, $header); + self::assertTrue(array_key_exists('epk', $header)); + self::assertTrue(array_key_exists('crv', $header['epk'])); + self::assertTrue(array_key_exists('kty', $header['epk'])); + self::assertTrue(array_key_exists('x', $header['epk'])); + self::assertTrue(array_key_exists('y', $header['epk'])); + self::assertEquals('P-256', $header['epk']['crv']); + self::assertEquals('EC', $header['epk']['kty']); + self::assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 192, $header)); + } + + public function testGetAgreementKeyWithA256KeyWrap() + { + $header = ['enc' => 'A256GCM']; + + $public = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + ]); + + $private = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ', + 'y' => 'e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck', + 'd' => 'VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw', + ]); + + $cek = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]; + foreach ($cek as $key => $value) { + $cek[$key] = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); + } + $cek = hex2bin(implode('', $cek)); + + $ecdh_es = new ECDHESA256KW(); + $encrypted_cek = $ecdh_es->wrapAgreementKey($public, $cek, 256, $header, $header); + self::assertTrue(array_key_exists('epk', $header)); + self::assertTrue(array_key_exists('crv', $header['epk'])); + self::assertTrue(array_key_exists('kty', $header['epk'])); + self::assertTrue(array_key_exists('x', $header['epk'])); + self::assertTrue(array_key_exists('y', $header['epk'])); + self::assertEquals('P-256', $header['epk']['crv']); + self::assertEquals('EC', $header['epk']['kty']); + self::assertEquals($cek, $ecdh_es->unwrapAgreementKey($private, $encrypted_cek, 256, $header)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The header parameter "epk" is missing + */ + public function testEPKParameterAreMissing() + { + $sender = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0', + 'y' => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps', + 'd' => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo', + ]); + + $ecdh_es = new ECDHES(); + $ecdh_es->getAgreementKey(256, 'A128GCM', $sender); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The header parameter "epk" is not an array of parameter + */ + public function testBadEPKParameter() + { + $header = ['epk' => 'foo']; + $sender = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-256', + 'x' => 'gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0', + 'y' => 'SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps', + 'd' => '0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo', + ]); + + $ecdh_es = new ECDHES(); + $ecdh_es->getAgreementKey(256, 'A128GCM', $sender, $header); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The key parameter "x" is missing. + */ + public function testECKeyHasMissingParameters() + { + $receiver = JWK::create([ + 'kty' => 'EC', + 'dir' => Base64Url::encode('ABCD'), + ]); + + $ecdh_es = new ECDHES(); + $ecdh_es->getAgreementKey(256, 'A128GCM', $receiver); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The curve "P-192" is not supported + */ + public function testUnsupportedCurve() + { + $header = [ + 'enc' => 'A128GCM', + 'apu' => 'QWxpY2U', + 'apv' => 'Qm9i', + ]; + + $receiver = JWK::create([ + 'kty' => 'EC', + 'crv' => 'P-192', + 'x' => 'm2Jmp98NRH83ramvp0VVIQJXK56ZEwuM', + 'y' => '84lz6hQtPJe9WFPPgEyOUwh3tuW2kOS_', + ]); + + $ecdh_es = new ECDHES(); + $ecdh_es->getAgreementKey(256, 'A128GCM', $receiver, $header); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3530a85 --- /dev/null +++ b/composer.json @@ -0,0 +1,36 @@ +{ + "name": "web-token/jwt-encryption-algorithm-ecdhes", + "description": "ECDH-ES Based Key Encryption Algorithms the JWT Framework.", + "type": "library", + "license": "MIT", + "keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"], + "homepage": "https://github.com/web-token", + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + },{ + "name": "All contributors", + "homepage": "https://github.com/web-token/jwt-core/contributors" + } + ], + "autoload": { + "psr-4": { + "Jose\\Component\\Encryption\\Algorithm\\KeyEncryption\\": "" + } + }, + "require": { + "web-token/jwt-encryption": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^6.0|^7.0" + }, + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..c8b3143 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + ./Tests/ + + + + + + ./ + + ./vendor + ./Tests + ./src + + + +