112 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| declare(strict_types=1);
 | |
| 
 | |
| namespace Jose\Component\Encryption\Serializer;
 | |
| 
 | |
| use InvalidArgumentException;
 | |
| use Jose\Component\Core\Util\Base64UrlSafe;
 | |
| use Jose\Component\Core\Util\JsonConverter;
 | |
| use Jose\Component\Encryption\JWE;
 | |
| use Jose\Component\Encryption\Recipient;
 | |
| use LogicException;
 | |
| use Throwable;
 | |
| use function count;
 | |
| use function is_array;
 | |
| 
 | |
| final class CompactSerializer implements JWESerializer
 | |
| {
 | |
|     public const NAME = 'jwe_compact';
 | |
| 
 | |
|     public function displayName(): string
 | |
|     {
 | |
|         return 'JWE Compact';
 | |
|     }
 | |
| 
 | |
|     public function name(): string
 | |
|     {
 | |
|         return self::NAME;
 | |
|     }
 | |
| 
 | |
|     public function serialize(JWE $jwe, ?int $recipientIndex = null): string
 | |
|     {
 | |
|         if ($recipientIndex === null) {
 | |
|             $recipientIndex = 0;
 | |
|         }
 | |
|         $recipient = $jwe->getRecipient($recipientIndex);
 | |
| 
 | |
|         $this->checkHasNoAAD($jwe);
 | |
|         $this->checkHasSharedProtectedHeader($jwe);
 | |
|         $this->checkRecipientHasNoHeader($jwe, $recipientIndex);
 | |
| 
 | |
|         return sprintf(
 | |
|             '%s.%s.%s.%s.%s',
 | |
|             $jwe->getEncodedSharedProtectedHeader(),
 | |
|             Base64UrlSafe::encodeUnpadded($recipient->getEncryptedKey() ?? ''),
 | |
|             Base64UrlSafe::encodeUnpadded($jwe->getIV() ?? ''),
 | |
|             Base64UrlSafe::encodeUnpadded($jwe->getCiphertext() ?? ''),
 | |
|             Base64UrlSafe::encodeUnpadded($jwe->getTag() ?? '')
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     public function unserialize(string $input): JWE
 | |
|     {
 | |
|         $parts = explode('.', $input);
 | |
|         if (count($parts) !== 5) {
 | |
|             throw new InvalidArgumentException('Unsupported input');
 | |
|         }
 | |
| 
 | |
|         try {
 | |
|             $encodedSharedProtectedHeader = $parts[0];
 | |
|             $sharedProtectedHeader = JsonConverter::decode(
 | |
|                 Base64UrlSafe::decodeNoPadding($encodedSharedProtectedHeader)
 | |
|             );
 | |
|             if (! is_array($sharedProtectedHeader)) {
 | |
|                 throw new InvalidArgumentException('Unsupported input.');
 | |
|             }
 | |
|             $encryptedKey = $parts[1] === '' ? null : Base64UrlSafe::decodeNoPadding($parts[1]);
 | |
|             $iv = Base64UrlSafe::decodeNoPadding($parts[2]);
 | |
|             $ciphertext = Base64UrlSafe::decodeNoPadding($parts[3]);
 | |
|             $tag = Base64UrlSafe::decodeNoPadding($parts[4]);
 | |
| 
 | |
|             return new JWE(
 | |
|                 $ciphertext,
 | |
|                 $iv,
 | |
|                 $tag,
 | |
|                 null,
 | |
|                 [],
 | |
|                 $sharedProtectedHeader,
 | |
|                 $encodedSharedProtectedHeader,
 | |
|                 [new Recipient([], $encryptedKey)]
 | |
|             );
 | |
|         } catch (Throwable $throwable) {
 | |
|             throw new InvalidArgumentException('Unsupported input', $throwable->getCode(), $throwable);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function checkHasNoAAD(JWE $jwe): void
 | |
|     {
 | |
|         if ($jwe->getAAD() !== null) {
 | |
|             throw new LogicException('This JWE has AAD and cannot be converted into Compact JSON.');
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function checkRecipientHasNoHeader(JWE $jwe, int $id): void
 | |
|     {
 | |
|         if (count($jwe->getSharedHeader()) !== 0 || count($jwe->getRecipient($id)->getHeader()) !== 0) {
 | |
|             throw new LogicException(
 | |
|                 'This JWE has shared header parameters or recipient header parameters and cannot be converted into Compact JSON.'
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function checkHasSharedProtectedHeader(JWE $jwe): void
 | |
|     {
 | |
|         if (count($jwe->getSharedProtectedHeader()) === 0) {
 | |
|             throw new LogicException(
 | |
|                 'This JWE does not have shared protected header parameters and cannot be converted into Compact JSON.'
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| }
 |