Skip to content

Commit

Permalink
Preparation 3.0 (#323)
Browse files Browse the repository at this point in the history
* Preparation 3.0
* Update with ECS and Rector
* Bugs fixed
  • Loading branch information
Spomky authored Dec 9, 2021
1 parent 87aa915 commit 0732973
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 131 deletions.
92 changes: 30 additions & 62 deletions ECDHES.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Jose\Component\Encryption\Algorithm\KeyEncryption;

use function array_key_exists;
Expand Down Expand Up @@ -38,8 +29,14 @@ public function allowedKeyTypes(): array
return ['EC', 'OKP'];
}

public function getAgreementKey(int $encryptionKeyLength, string $algorithm, JWK $recipientKey, ?JWK $senderKey, array $complete_header = [], array &$additional_header_values = []): string
{
public function getAgreementKey(
int $encryptionKeyLength,
string $algorithm,
JWK $recipientKey,
?JWK $senderKey,
array $complete_header = [],
array &$additional_header_values = []
): string {
if ($recipientKey->has('d')) {
[$public_key, $private_key] = $this->getKeysFromPrivateKeyAndHeader($recipientKey, $complete_header);
} else {
Expand All @@ -54,9 +51,6 @@ public function getAgreementKey(int $encryptionKeyLength, string $algorithm, JWK
return ConcatKDF::generate($agreed_key, $algorithm, $encryptionKeyLength, $apu, $apv);
}

/**
* @throws InvalidArgumentException if the curve is not supported
*/
public function calculateAgreementKey(JWK $private_key, JWK $public_key): string
{
switch ($public_key->get('crv')) {
Expand All @@ -70,12 +64,12 @@ public function calculateAgreementKey(JWK $private_key, JWK $public_key): string
$privatePem = ECKey::convertPrivateKeyToPEM($private_key);

$res = openssl_pkey_derive($publicPem, $privatePem, $curve->getSize());
if (false === $res) {
if ($res === false) {
throw new RuntimeException('Unable to derive the key');
}

return $res;
} catch (Throwable $throwable) {
} catch (Throwable) {
//Does nothing. Will fallback to the pure PHP function
}
}
Expand Down Expand Up @@ -111,8 +105,6 @@ public function getKeyManagementMode(): string
}

/**
* @throws InvalidArgumentException if the curve is not supported
*
* @return JWK[]
*/
private function getKeysFromPublicKey(JWK $recipient_key, array &$additional_header_values): array
Expand All @@ -137,15 +129,15 @@ private function getKeysFromPublicKey(JWK $recipient_key, array &$additional_hea
default:
throw new InvalidArgumentException(sprintf('The curve "%s" is not supported', $public_key->get('crv')));
}
$epk = $private_key->toPublic()->all();
$epk = $private_key->toPublic()
->all()
;
$additional_header_values['epk'] = $epk;

return [$public_key, $private_key];
}

/**
* @throws InvalidArgumentException if the curves are different
*
* @return JWK[]
*/
private function getKeysFromPrivateKeyAndHeader(JWK $recipient_key, array $complete_header): array
Expand All @@ -160,15 +152,12 @@ private function getKeysFromPrivateKeyAndHeader(JWK $recipient_key, array $compl
return [$public_key, $private_key];
}

/**
* @throws InvalidArgumentException if the ephemeral public key is missing or invalid
*/
private function getPublicKey(array $complete_header): JWK
{
if (!isset($complete_header['epk'])) {
if (! isset($complete_header['epk'])) {
throw new InvalidArgumentException('The header parameter "epk" is missing.');
}
if (!is_array($complete_header['epk'])) {
if (! is_array($complete_header['epk'])) {
throw new InvalidArgumentException('The header parameter "epk" is not an array of parameters');
}
$public_key = new JWK($complete_header['epk']);
Expand All @@ -177,16 +166,13 @@ private function getPublicKey(array $complete_header): JWK
return $public_key;
}

/**
* @throws InvalidArgumentException if the key is invalid
*/
private function checkKey(JWK $key, bool $is_private): void
{
if (!in_array($key->get('kty'), $this->allowedKeyTypes(), true)) {
if (! in_array($key->get('kty'), $this->allowedKeyTypes(), true)) {
throw new InvalidArgumentException('Wrong key type.');
}
foreach (['x', 'crv'] as $k) {
if (!$key->has($k)) {
if (! $key->has($k)) {
throw new InvalidArgumentException(sprintf('The key parameter "%s" is missing.', $k));
}
}
Expand All @@ -195,7 +181,7 @@ private function checkKey(JWK $key, bool $is_private): void
case 'P-256':
case 'P-384':
case 'P-521':
if (!$key->has('y')) {
if (! $key->has('y')) {
throw new InvalidArgumentException('The key parameter "y" is missing.');
}

Expand All @@ -207,57 +193,44 @@ private function checkKey(JWK $key, bool $is_private): void
default:
throw new InvalidArgumentException(sprintf('The curve "%s" is not supported', $key->get('crv')));
}
if (true === $is_private && !$key->has('d')) {
if ($is_private === true && ! $key->has('d')) {
throw new InvalidArgumentException('The key parameter "d" is missing.');
}
}

/**
* @throws InvalidArgumentException if the curve is not supported
*/
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));
}
return match ($crv) {
'P-256' => NistCurve::curve256(),
'P-384' => NistCurve::curve384(),
'P-521' => NistCurve::curve521(),
default => throw new InvalidArgumentException(sprintf('The curve "%s" is not supported', $crv)),
};
}

private function convertBase64ToBigInteger(string $value): BigInteger
{
$data = unpack('H*', Base64UrlSafe::decode($value));
if (!is_array($data) || !isset($data[1])) {
if (! is_array($data) || ! isset($data[1])) {
throw new InvalidArgumentException('Unable to convert base64 to integer');
}

return BigInteger::fromBase($data[1], 16);
}

/**
* @throws InvalidArgumentException if the data cannot be converted
*/
private function convertDecToBin(BigInteger $dec): string
{
if ($dec->compareTo(BigInteger::zero()) < 0) {
throw new InvalidArgumentException('Unable to convert negative integer to string');
}
$hex = $dec->toBase(16);

if (0 !== mb_strlen($hex, '8bit') % 2) {
$hex = '0'.$hex;
if (mb_strlen($hex, '8bit') % 2 !== 0) {
$hex = '0' . $hex;
}

$bin = hex2bin($hex);
if (false === $bin) {
if ($bin === false) {
throw new InvalidArgumentException('Unable to convert integer to string');
}

Expand All @@ -266,8 +239,6 @@ private function convertDecToBin(BigInteger $dec): string

/**
* @param string $curve The curve
*
* @throws InvalidArgumentException if the curve is not supported
*/
private function createOKPKey(string $curve): JWK
{
Expand Down Expand Up @@ -300,12 +271,9 @@ private function createOKPKey(string $curve): JWK
]);
}

/**
* @throws RuntimeException if the extension "sodium" is not available
*/
private function checkSodiumExtensionIsAvailable(): void
{
if (!extension_loaded('sodium')) {
if (! extension_loaded('sodium')) {
throw new RuntimeException('The extension "sodium" is not available. Please install it to use this method');
}
}
Expand Down
11 changes: 1 addition & 10 deletions ECDHESA128KW.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Jose\Component\Encryption\Algorithm\KeyEncryption;

use AESKW\A128KW as Wrapper;
Expand All @@ -22,7 +13,7 @@ public function name(): string
return 'ECDH-ES+A128KW';
}

protected function getWrapper()
protected function getWrapper(): Wrapper
{
return new Wrapper();
}
Expand Down
11 changes: 1 addition & 10 deletions ECDHESA192KW.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Jose\Component\Encryption\Algorithm\KeyEncryption;

use AESKW\A192KW as Wrapper;
Expand All @@ -22,7 +13,7 @@ public function name(): string
return 'ECDH-ES+A192KW';
}

protected function getWrapper()
protected function getWrapper(): Wrapper
{
return new Wrapper();
}
Expand Down
11 changes: 1 addition & 10 deletions ECDHESA256KW.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Jose\Component\Encryption\Algorithm\KeyEncryption;

use AESKW\A256KW as Wrapper;
Expand All @@ -22,7 +13,7 @@ public function name(): string
return 'ECDH-ES+A256KW';
}

protected function getWrapper()
protected function getWrapper(): Wrapper
{
return new Wrapper();
}
Expand Down
53 changes: 34 additions & 19 deletions ECDHESAESKW.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,11 @@

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Jose\Component\Encryption\Algorithm\KeyEncryption;

use AESKW\A128KW;
use AESKW\A192KW;
use AESKW\A256KW;
use Jose\Component\Core\JWK;

abstract class ECDHESAESKW implements KeyAgreementWithKeyWrapping
Expand All @@ -22,19 +16,43 @@ public function allowedKeyTypes(): array
return ['EC', 'OKP'];
}

public function wrapAgreementKey(JWK $recipientKey, ?JWK $senderKey, string $cek, int $encryption_key_length, array $complete_header, array &$additional_header_values): string
{
public function wrapAgreementKey(
JWK $recipientKey,
?JWK $senderKey,
string $cek,
int $encryption_key_length,
array $complete_header,
array &$additional_header_values
): string {
$ecdh_es = new ECDHES();
$agreement_key = $ecdh_es->getAgreementKey($this->getKeyLength(), $this->name(), $recipientKey->toPublic(), $senderKey, $complete_header, $additional_header_values);
$agreement_key = $ecdh_es->getAgreementKey(
$this->getKeyLength(),
$this->name(),
$recipientKey->toPublic(),
$senderKey,
$complete_header,
$additional_header_values
);
$wrapper = $this->getWrapper();

return $wrapper::wrap($agreement_key, $cek);
}

public function unwrapAgreementKey(JWK $recipientKey, ?JWK $senderKey, string $encrypted_cek, int $encryption_key_length, array $complete_header): string
{
public function unwrapAgreementKey(
JWK $recipientKey,
?JWK $senderKey,
string $encrypted_cek,
int $encryption_key_length,
array $complete_header
): string {
$ecdh_es = new ECDHES();
$agreement_key = $ecdh_es->getAgreementKey($this->getKeyLength(), $this->name(), $recipientKey, $senderKey, $complete_header);
$agreement_key = $ecdh_es->getAgreementKey(
$this->getKeyLength(),
$this->name(),
$recipientKey,
$senderKey,
$complete_header
);
$wrapper = $this->getWrapper();

return $wrapper::unwrap($agreement_key, $encrypted_cek);
Expand All @@ -45,10 +63,7 @@ public function getKeyManagementMode(): string
return self::MODE_WRAP;
}

/**
* @return \AESKW\A128KW|\AESKW\A192KW|\AESKW\A256KW
*/
abstract protected function getWrapper();
abstract protected function getWrapper(): A128KW|A192KW|A256KW;

abstract protected function getKeyLength(): int;
}
Loading

0 comments on commit 0732973

Please sign in to comment.