decryptCek( base64_decode( $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] ), json_decode( $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER], true ) ); $cipherOptions['KeySize'] = strlen($cek) * 8; $cipherOptions['Cipher'] = $this->getCipherFromAesName( $envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] ); $decryptionStream = $this->getDecryptingStream( $cipherText, $cek, $cipherOptions ); unset($cek); return $decryptionStream; } private function getTagFromCiphertextStream( StreamInterface $cipherText, $tagLength ) { $cipherTextSize = $cipherText->getSize(); if ($cipherTextSize == null || $cipherTextSize <= 0) { throw new \RuntimeException('Cannot decrypt a stream of unknown' . ' size.'); } return (string) new LimitStream( $cipherText, $tagLength, $cipherTextSize - $tagLength ); } private function getStrippedCiphertextStream( StreamInterface $cipherText, $tagLength ) { $cipherTextSize = $cipherText->getSize(); if ($cipherTextSize == null || $cipherTextSize <= 0) { throw new \RuntimeException('Cannot decrypt a stream of unknown' . ' size.'); } return new LimitStream( $cipherText, $cipherTextSize - $tagLength, 0 ); } /** * Generates a stream that wraps the cipher text with the proper cipher and * uses the content encryption key (CEK) to decrypt the data when read. * * @param string $cipherText Plain-text data to be encrypted using the * materials, algorithm, and data provided. * @param string $cek A content encryption key for use by the stream for * encrypting the plaintext data. * @param array $cipherOptions Options for use in determining the cipher to * be used for encrypting data. * * @return AesStreamInterface * * @internal */ protected function getDecryptingStream( $cipherText, $cek, $cipherOptions ) { $cipherTextStream = Psr7\stream_for($cipherText); switch ($cipherOptions['Cipher']) { case 'gcm': $cipherOptions['Tag'] = $this->getTagFromCiphertextStream( $cipherTextStream, $cipherOptions['TagLength'] ); return new AesGcmDecryptingStream( $this->getStrippedCiphertextStream( $cipherTextStream, $cipherOptions['TagLength'] ), $cek, $cipherOptions['Iv'], $cipherOptions['Tag'], $cipherOptions['Aad'] = isset($cipherOptions['Aad']) ? $cipherOptions['Aad'] : null, $cipherOptions['TagLength'] ?: null, $cipherOptions['KeySize'] ); default: $cipherMethod = $this->buildCipherMethod( $cipherOptions['Cipher'], $cipherOptions['Iv'], $cipherOptions['KeySize'] ); return new AesDecryptingStream( $cipherTextStream, $cek, $cipherMethod ); } } }