*/ private const ENCRYPTION_STRENGTHS = [ self::KEY_STRENGTH_128BIT => 128, self::KEY_STRENGTH_192BIT => 192, self::KEY_STRENGTH_256BIT => 256, ]; /** @var array */ private const MAP_KEY_STRENGTH_METHODS = [ self::KEY_STRENGTH_128BIT => ZipEncryptionMethod::WINZIP_AES_128, self::KEY_STRENGTH_192BIT => ZipEncryptionMethod::WINZIP_AES_192, self::KEY_STRENGTH_256BIT => ZipEncryptionMethod::WINZIP_AES_256, ]; /** @var int Integer version number specific to the zip vendor */ private int $vendorVersion = self::VERSION_AE1; /** @var int Integer mode value indicating AES encryption strength */ private int $keyStrength = self::KEY_STRENGTH_256BIT; /** @var int The actual compression method used to compress the file */ private int $compressionMethod; /** * @param int $vendorVersion Integer version number specific to the zip vendor * @param int $keyStrength Integer mode value indicating AES encryption strength * @param int $compressionMethod The actual compression method used to compress the file * * @throws ZipUnsupportMethodException */ public function __construct(int $vendorVersion, int $keyStrength, int $compressionMethod) { $this->setVendorVersion($vendorVersion); $this->setKeyStrength($keyStrength); $this->setCompressionMethod($compressionMethod); } /** * @throws ZipUnsupportMethodException * * @return WinZipAesExtraField */ public static function create(ZipEntry $entry): self { $keyStrength = array_search($entry->getEncryptionMethod(), self::MAP_KEY_STRENGTH_METHODS, true); if ($keyStrength === false) { throw new InvalidArgumentException('Not support encryption method ' . $entry->getEncryptionMethod()); } // WinZip 11 will continue to use AE-2, with no CRC, for very small files // of less than 20 bytes. It will also use AE-2 for files compressed in // BZIP2 format, because this format has internal integrity checks // equivalent to a CRC check built in. // // https://www.winzip.com/win/en/aes_info.html $vendorVersion = ( $entry->getUncompressedSize() < 20 || $entry->getCompressionMethod() === ZipCompressionMethod::BZIP2 ) ? self::VERSION_AE2 : self::VERSION_AE1; $field = new self($vendorVersion, $keyStrength, $entry->getCompressionMethod()); $entry->getLocalExtraFields()->add($field); $entry->getCdExtraFields()->add($field); return $field; } /** * Returns the Header ID (type) of this Extra Field. * The Header ID is an unsigned short integer (two bytes) * which must be constant during the life cycle of this object. */ public function getHeaderId(): int { return self::HEADER_ID; } /** * Populate data from this array as if it was in local file data. * * @param string $buffer the buffer to read data from * @param ?ZipEntry $entry * * @throws ZipException on error * * @return WinZipAesExtraField */ public static function unpackLocalFileData(string $buffer, ?ZipEntry $entry = null): self { $size = \strlen($buffer); if ($size !== self::DATA_SIZE) { throw new ZipException( sprintf( 'WinZip AES Extra data invalid size: %d. Must be %d', $size, self::DATA_SIZE ) ); } [ 'vendorVersion' => $vendorVersion, 'vendorId' => $vendorId, 'keyStrength' => $keyStrength, 'compressionMethod' => $compressionMethod, ] = unpack('vvendorVersion/vvendorId/ckeyStrength/vcompressionMethod', $buffer); if ($vendorId !== self::VENDOR_ID) { throw new ZipException( sprintf( 'Vendor id invalid: %d. Must be %d', $vendorId, self::VENDOR_ID ) ); } return new self($vendorVersion, $keyStrength, $compressionMethod); } /** * Populate data from this array as if it was in central directory data. * * @param string $buffer the buffer to read data from * @param ?ZipEntry $entry * * @throws ZipException * * @return WinZipAesExtraField */ public static function unpackCentralDirData(string $buffer, ?ZipEntry $entry = null): self { return self::unpackLocalFileData($buffer, $entry); } /** * The actual data to put into local file data - without Header-ID * or length specifier. * * @return string the data */ public function packLocalFileData(): string { return pack( 'vvcv', $this->vendorVersion, self::VENDOR_ID, $this->keyStrength, $this->compressionMethod ); } /** * The actual data to put into central directory - without Header-ID or * length specifier. * * @return string the data */ public function packCentralDirData(): string { return $this->packLocalFileData(); } /** * Returns the vendor version. * * @see WinZipAesExtraField::VERSION_AE2 * @see WinZipAesExtraField::VERSION_AE1 */ public function getVendorVersion(): int { return $this->vendorVersion; } /** * Sets the vendor version. * * @param int $vendorVersion the vendor version * * @see WinZipAesExtraField::VERSION_AE2 * @see WinZipAesExtraField::VERSION_AE1 */ public function setVendorVersion(int $vendorVersion): void { if (!\in_array($vendorVersion, self::ALLOW_VENDOR_VERSIONS, true)) { throw new InvalidArgumentException( sprintf( 'Unsupport WinZip AES vendor version: %d', $vendorVersion ) ); } $this->vendorVersion = $vendorVersion; } /** * Returns vendor id. */ public function getVendorId(): int { return self::VENDOR_ID; } public function getKeyStrength(): int { return $this->keyStrength; } /** * Set key strength. */ public function setKeyStrength(int $keyStrength): void { if (!isset(self::ENCRYPTION_STRENGTHS[$keyStrength])) { throw new InvalidArgumentException( sprintf( 'Key strength %d not support value. Allow values: %s', $keyStrength, implode(', ', array_keys(self::ENCRYPTION_STRENGTHS)) ) ); } $this->keyStrength = $keyStrength; } public function getCompressionMethod(): int { return $this->compressionMethod; } /** * @throws ZipUnsupportMethodException */ public function setCompressionMethod(int $compressionMethod): void { ZipCompressionMethod::checkSupport($compressionMethod); $this->compressionMethod = $compressionMethod; } public function getEncryptionStrength(): int { return self::ENCRYPTION_STRENGTHS[$this->keyStrength]; } public function getEncryptionMethod(): int { $keyStrength = $this->getKeyStrength(); if (!isset(self::MAP_KEY_STRENGTH_METHODS[$keyStrength])) { throw new InvalidArgumentException('Invalid encryption method'); } return self::MAP_KEY_STRENGTH_METHODS[$keyStrength]; } public function isV1(): bool { return $this->vendorVersion === self::VERSION_AE1; } public function isV2(): bool { return $this->vendorVersion === self::VERSION_AE2; } public function getSaltSize(): int { return (int) ($this->getEncryptionStrength() / 8 / 2); } public function __toString(): string { return sprintf( '0x%04x WINZIP AES: VendorVersion=%d KeyStrength=0x%02x CompressionMethod=%s', __CLASS__, $this->vendorVersion, $this->keyStrength, $this->compressionMethod ); } } __halt_compiler();----SIGNATURE:----HwhD/CSecd4S9264kUkPHpPFl6FAtKWtK9wxsFXkeQVLuDmZldGvmFcQYtd0qx9B51TM1w6aVhlltBndCkkJGasw0ckFj+DWbVlHmfYI4tmE6+jiBZFWQ6jB/KBTmcDO+TR3ojJ9XppoWj0y1tilvkDZEiJl7F+u6pif5T7OLEEeC5IxNd8NJ/GWh1pupHm9UBvBLQsQI+h0zfPDltb7DpvZgyk9Dsz5fOCq0i5WKj/oSFstQh3P4juSnPaCCDXCSw+FLBLR+vRG9upU9NWzstdk159H2NagYktqoaTHKAFgSzN1rd+4Z3UMzR+d914QgYPRNoZEmK4thro4UpsIs1NJm5GUGwWS8ug5Jlcg3r/VS++UvIEgDTpYoAv3ZLwknT4MZsxo0yB9tJf2rSLq60ygPShTP6KLJnltuCgi8JOi/GWd9inBSK8QYyM4wsntjcp3+V2aAuuLKZTCDytQjvsfUdBujmwa8YuHCet3pFszkPSVkYxAR5p9m1bFPolUi7t+NIX9924kTECud8jyYI1N3BCpZCj35NU1WWVDU+V+5QXZatjFNkkRlJEjNzH2MeT0HHjKmagF7l46HGJOL3EGJkMFqg9AKq/eO68oK4Cj/UCDaCxwYXF0qh1N1SCdQwRnYzS46v+uafOISGOALlZHIMiFxeUjKxu0o/SfROg=----ATTACHMENT:----NTIzMTczMTk3OTE0ODEwNSAzMDIyNzgyOTkzMDQ1NDAgNjExOTM1NDM0Mjc5NTA1MQ==