do include the standard ZIP CRC-32 value. * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see * WinZipAesEntryExtraField::getVendorVersion(). */ const VV_AE_1 = 1; /** * Entries of this type do not include the standard ZIP CRC-32 value. * For use with @see WinZipAesEntryExtraField::setVendorVersion()}/@see * WinZipAesEntryExtraField::getVendorVersion(). */ const VV_AE_2 = 2; const KEY_STRENGTH_128BIT = 128; const KEY_STRENGTH_192BIT = 192; const KEY_STRENGTH_256BIT = 256; protected static $keyStrengths = [ self::KEY_STRENGTH_128BIT => 0x01, self::KEY_STRENGTH_192BIT => 0x02, self::KEY_STRENGTH_256BIT => 0x03, ]; protected static $encryptionMethods = [ self::KEY_STRENGTH_128BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_128, self::KEY_STRENGTH_192BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_192, self::KEY_STRENGTH_256BIT => ZipFile::ENCRYPTION_METHOD_WINZIP_AES_256, ]; /** * Vendor version. * * @var int */ protected $vendorVersion = self::VV_AE_1; /** * Encryption strength. * * @var int */ protected $encryptionStrength = self::KEY_STRENGTH_256BIT; /** * Zip compression method. * * @var int */ protected $method; /** * 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. * * @return int */ public static function getHeaderId() { return 0x9901; } /** * Returns the vendor version. * * @see WinZipAesEntryExtraField::VV_AE_1 * @see WinZipAesEntryExtraField::VV_AE_2 */ public function getVendorVersion() { return $this->vendorVersion & 0xffff; } /** * Sets the vendor version. * * @param int $vendorVersion the vendor version * * @throws ZipException unsupport vendor version * * @see WinZipAesEntryExtraField::VV_AE_1 * @see WinZipAesEntryExtraField::VV_AE_2 */ public function setVendorVersion($vendorVersion) { if ($vendorVersion < self::VV_AE_1 || $vendorVersion > self::VV_AE_2) { throw new ZipException($vendorVersion); } $this->vendorVersion = $vendorVersion; } /** * Returns vendor id. * * @return int */ public function getVendorId() { return self::VENDOR_ID; } /** * @throws ZipException * * @return bool|int */ public function getKeyStrength() { return self::keyStrength($this->encryptionStrength); } /** * @param int $encryptionStrength encryption strength as bits * * @throws ZipException if unsupport encryption strength * * @return int */ public static function keyStrength($encryptionStrength) { $flipKeyStrength = array_flip(self::$keyStrengths); if (!isset($flipKeyStrength[$encryptionStrength])) { throw new ZipException('Unsupport encryption strength ' . $encryptionStrength); } return $flipKeyStrength[$encryptionStrength]; } /** * Returns compression method. * * @return int */ public function getMethod() { return $this->method & 0xffff; } /** * Internal encryption method. * * @throws ZipException * * @return int */ public function getEncryptionMethod() { return isset(self::$encryptionMethods[$this->getKeyStrength()]) ? self::$encryptionMethods[$this->getKeyStrength()] : self::$encryptionMethods[self::KEY_STRENGTH_256BIT]; } /** * @param int $encryptionMethod * * @throws ZipException * * @return int */ public static function getKeyStrangeFromEncryptionMethod($encryptionMethod) { $flipKey = array_flip(self::$encryptionMethods); if (!isset($flipKey[$encryptionMethod])) { throw new ZipException('Unsupport encryption method ' . $encryptionMethod); } return $flipKey[$encryptionMethod]; } /** * Sets compression method. * * @param int $compressionMethod Compression method * * @throws ZipException compression method out of range */ public function setMethod($compressionMethod) { if ($compressionMethod < 0x0000 || $compressionMethod > 0xffff) { throw new ZipException('Compression method out of range'); } $this->method = $compressionMethod; } /** * Set key strength. * * @param int $keyStrength */ public function setKeyStrength($keyStrength) { $this->encryptionStrength = self::encryptionStrength($keyStrength); } /** * Returns encryption strength. * * @param int $keyStrength key strength in bits * * @return int */ public static function encryptionStrength($keyStrength) { return isset(self::$keyStrengths[$keyStrength]) ? self::$keyStrengths[$keyStrength] : self::$keyStrengths[self::KEY_STRENGTH_128BIT]; } /** * Serializes a Data Block. * * @return string */ public function serialize() { return pack( 'vvcv', $this->vendorVersion, self::VENDOR_ID, $this->encryptionStrength, $this->method ); } /** * Initializes this Extra Field by deserializing a Data Block. * * @param string $data * * @throws ZipException */ public function deserialize($data) { $size = \strlen($data); if ($size !== self::DATA_SIZE) { throw new ZipException('WinZip AES Extra data invalid size: ' . $size . '. Must be ' . self::DATA_SIZE); } /** * @var int $vendorVersion * @var int $vendorId * @var int $keyStrength * @var int $method */ $unpack = unpack('vvendorVersion/vvendorId/ckeyStrength/vmethod', $data); $this->setVendorVersion($unpack['vendorVersion']); if ($unpack['vendorId'] !== self::VENDOR_ID) { throw new ZipException('Vendor id invalid: ' . $unpack['vendorId'] . '. Must be ' . self::VENDOR_ID); } $this->setKeyStrength(self::keyStrength($unpack['keyStrength'])); // checked $this->setMethod($unpack['method']); } }