| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <?php
- namespace PhpZip\Extra\Fields;
- use PhpZip\Exception\ZipException;
- use PhpZip\Extra\ExtraField;
- use PhpZip\ZipFile;
- /**
- * WinZip AES Extra Field.
- *
- * @see http://www.winzip.com/win/en/aes_info.htm AES Encryption Information: Encryption Specification AE-1 and AE-2
- * (WinZip Computing, S.L.)
- * @see http://www.winzip.com/win/en/aes_tips.htm AES Coding Tips for Developers (WinZip Computing, S.L.)
- *
- * @author Ne-Lexa alexey@nelexa.ru
- * @license MIT
- */
- class WinZipAesEntryExtraField implements ExtraField
- {
- const DATA_SIZE = 7;
- const VENDOR_ID = 17729; // 'A' | ('E' << 8);
- /**
- * Entries of this type <em>do</em> 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 <em>not</em> 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']);
- }
- }
|