<?php
 declare(strict_types=1); namespace Jose\Component\Encryption\Algorithm\KeyEncryption\Util; use InvalidArgumentException; use Jose\Component\Core\Util\Base64UrlSafe; use function strlen; use const STR_PAD_LEFT; final readonly class ConcatKDF { public static function generate( string $Z, string $algorithm, int $encryption_key_size, string $apu = '', string $apv = '' ): string { $apu = ! self::isEmpty($apu) ? Base64UrlSafe::decodeNoPadding($apu) : ''; $apv = ! self::isEmpty($apv) ? Base64UrlSafe::decodeNoPadding($apv) : ''; $encryption_segments = [ self::toInt32Bits(1), $Z, self::toInt32Bits(strlen($algorithm)) . $algorithm, self::toInt32Bits(strlen($apu)) . $apu, self::toInt32Bits(strlen($apv)) . $apv, self::toInt32Bits($encryption_key_size), '', ]; $input = implode('', $encryption_segments); $hash = hash('sha256', $input, true); return substr($hash, 0, $encryption_key_size / 8); } private static function toInt32Bits(int $value): string { $result = hex2bin(str_pad(dechex($value), 8, '0', STR_PAD_LEFT)); if ($result === false) { throw new InvalidArgumentException('Invalid result'); } return $result; } private static function isEmpty(?string $value): bool { return $value === null || $value === ''; } } 