ZipPasswordTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <?php
  2. namespace PhpZip;
  3. use PhpZip\Exception\ZipAuthenticationException;
  4. use PhpZip\Model\ZipInfo;
  5. use PhpZip\Util\CryptoUtil;
  6. class ZipPasswordTest extends ZipFileAddDirTest
  7. {
  8. /**
  9. * Test archive password.
  10. */
  11. public function testSetPassword()
  12. {
  13. $password = base64_encode(CryptoUtil::randomBytes(100));
  14. $badPassword = "sdgt43r23wefe";
  15. // create encryption password with ZipCrypto
  16. $zipFile = new ZipFile();
  17. $zipFile->addDir(__DIR__);
  18. $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
  19. $zipFile->saveAsFile($this->outputFilename);
  20. $zipFile->close();
  21. self::assertCorrectZipArchive($this->outputFilename, $password);
  22. // check bad password for ZipCrypto
  23. $zipFile->openFile($this->outputFilename);
  24. $zipFile->setReadPassword($badPassword);
  25. foreach ($zipFile->getListFiles() as $entryName) {
  26. try {
  27. $zipFile[$entryName];
  28. self::fail("Expected Exception has not been raised.");
  29. } catch (ZipAuthenticationException $ae) {
  30. self::assertNotNull($ae);
  31. }
  32. }
  33. // check correct password for ZipCrypto
  34. $zipFile->setReadPassword($password);
  35. foreach ($zipFile->getAllInfo() as $info) {
  36. self::assertTrue($info->isEncrypted());
  37. self::assertContains('ZipCrypto', $info->getMethodName());
  38. $decryptContent = $zipFile[$info->getName()];
  39. self::assertNotEmpty($decryptContent);
  40. self::assertContains('<?php', $decryptContent);
  41. }
  42. // change encryption method to WinZip Aes and update file
  43. $zipFile->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
  44. $zipFile->saveAsFile($this->outputFilename);
  45. $zipFile->close();
  46. self::assertCorrectZipArchive($this->outputFilename, $password);
  47. // check from WinZip AES encryption
  48. $zipFile->openFile($this->outputFilename);
  49. // set bad password WinZip AES
  50. $zipFile->setReadPassword($badPassword);
  51. foreach ($zipFile->getListFiles() as $entryName) {
  52. try {
  53. $zipFile[$entryName];
  54. self::fail("Expected Exception has not been raised.");
  55. } catch (ZipAuthenticationException $ae) {
  56. self::assertNotNull($ae);
  57. }
  58. }
  59. // set correct password WinZip AES
  60. $zipFile->setReadPassword($password);
  61. foreach ($zipFile->getAllInfo() as $info) {
  62. self::assertTrue($info->isEncrypted());
  63. self::assertContains('WinZip', $info->getMethodName());
  64. $decryptContent = $zipFile[$info->getName()];
  65. self::assertNotEmpty($decryptContent);
  66. self::assertContains('<?php', $decryptContent);
  67. }
  68. // clear password
  69. $zipFile->addFromString('file1', '');
  70. $zipFile->removePassword();
  71. $zipFile->addFromString('file2', '');
  72. $zipFile->saveAsFile($this->outputFilename);
  73. $zipFile->close();
  74. self::assertCorrectZipArchive($this->outputFilename);
  75. // check remove password
  76. $zipFile->openFile($this->outputFilename);
  77. foreach ($zipFile->getAllInfo() as $info) {
  78. self::assertFalse($info->isEncrypted());
  79. }
  80. $zipFile->close();
  81. }
  82. public function testTraditionalEncryption()
  83. {
  84. $password = base64_encode(CryptoUtil::randomBytes(50));
  85. $zip = new ZipFile();
  86. $zip->addDirRecursive($this->outputDirname);
  87. $zip->setPassword($password, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
  88. $zip->saveAsFile($this->outputFilename);
  89. $zip->close();
  90. self::assertCorrectZipArchive($this->outputFilename, $password);
  91. $zip->openFile($this->outputFilename);
  92. $zip->setReadPassword($password);
  93. self::assertFilesResult($zip, array_keys(self::$files));
  94. foreach ($zip->getAllInfo() as $info) {
  95. if (!$info->isFolder()) {
  96. self::assertTrue($info->isEncrypted());
  97. self::assertContains('ZipCrypto', $info->getMethodName());
  98. }
  99. }
  100. $zip->close();
  101. }
  102. /**
  103. * @dataProvider winZipKeyStrengthProvider
  104. * @param int $encryptionMethod
  105. * @param int $bitSize
  106. */
  107. public function testWinZipAesEncryption($encryptionMethod, $bitSize)
  108. {
  109. $password = base64_encode(CryptoUtil::randomBytes(50));
  110. $zip = new ZipFile();
  111. $zip->addDirRecursive($this->outputDirname);
  112. $zip->setPassword($password, $encryptionMethod);
  113. $zip->saveAsFile($this->outputFilename);
  114. $zip->close();
  115. self::assertCorrectZipArchive($this->outputFilename, $password);
  116. $zip->openFile($this->outputFilename);
  117. $zip->setReadPassword($password);
  118. self::assertFilesResult($zip, array_keys(self::$files));
  119. foreach ($zip->getAllInfo() as $info) {
  120. if (!$info->isFolder()) {
  121. self::assertTrue($info->isEncrypted());
  122. self::assertEquals($info->getEncryptionMethod(), $encryptionMethod);
  123. self::assertContains('WinZip AES-' . $bitSize, $info->getMethodName());
  124. }
  125. }
  126. $zip->close();
  127. }
  128. /**
  129. * @return array
  130. */
  131. public function winZipKeyStrengthProvider()
  132. {
  133. return [
  134. [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_128, 128],
  135. [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_192, 192],
  136. [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES, 256],
  137. [ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES_256, 256],
  138. ];
  139. }
  140. public function testEncryptionEntries()
  141. {
  142. $password1 = '353442434235424234';
  143. $password2 = 'adgerhvrwjhqqehtqhkbqrgewg';
  144. $zip = new ZipFile();
  145. $zip->addDir($this->outputDirname);
  146. $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
  147. $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
  148. $zip->saveAsFile($this->outputFilename);
  149. $zip->close();
  150. $zip->openFile($this->outputFilename);
  151. $zip->setReadPasswordEntry('.hidden', $password1);
  152. $zip->setReadPasswordEntry('text file.txt', $password2);
  153. self::assertFilesResult($zip, [
  154. '.hidden',
  155. 'text file.txt',
  156. 'Текстовый документ.txt',
  157. 'empty dir/',
  158. ]);
  159. $info = $zip->getEntryInfo('.hidden');
  160. self::assertTrue($info->isEncrypted());
  161. self::assertContains('ZipCrypto', $info->getMethodName());
  162. $info = $zip->getEntryInfo('text file.txt');
  163. self::assertTrue($info->isEncrypted());
  164. self::assertContains('WinZip AES', $info->getMethodName());
  165. self::assertFalse($zip->getEntryInfo('Текстовый документ.txt')->isEncrypted());
  166. self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
  167. $zip->close();
  168. }
  169. public function testEncryptionEntriesWithDefaultPassword()
  170. {
  171. $password1 = '353442434235424234';
  172. $password2 = 'adgerhvrwjhqqehtqhkbqrgewg';
  173. $defaultPassword = ' f f f f f ffff f5 ';
  174. $zip = new ZipFile();
  175. $zip->addDir($this->outputDirname);
  176. $zip->setPassword($defaultPassword);
  177. $zip->setPasswordEntry('.hidden', $password1, ZipFileInterface::ENCRYPTION_METHOD_TRADITIONAL);
  178. $zip->setPasswordEntry('text file.txt', $password2, ZipFileInterface::ENCRYPTION_METHOD_WINZIP_AES);
  179. $zip->saveAsFile($this->outputFilename);
  180. $zip->close();
  181. $zip->openFile($this->outputFilename);
  182. $zip->setReadPassword($defaultPassword);
  183. $zip->setReadPasswordEntry('.hidden', $password1);
  184. $zip->setReadPasswordEntry('text file.txt', $password2);
  185. self::assertFilesResult($zip, [
  186. '.hidden',
  187. 'text file.txt',
  188. 'Текстовый документ.txt',
  189. 'empty dir/',
  190. ]);
  191. $info = $zip->getEntryInfo('.hidden');
  192. self::assertTrue($info->isEncrypted());
  193. self::assertContains('ZipCrypto', $info->getMethodName());
  194. $info = $zip->getEntryInfo('text file.txt');
  195. self::assertTrue($info->isEncrypted());
  196. self::assertContains('WinZip AES', $info->getMethodName());
  197. $info = $zip->getEntryInfo('Текстовый документ.txt');
  198. self::assertTrue($info->isEncrypted());
  199. self::assertContains('WinZip AES', $info->getMethodName());
  200. self::assertFalse($zip->getEntryInfo('empty dir/')->isEncrypted());
  201. $zip->close();
  202. }
  203. /**
  204. * @expectedException \PhpZip\Exception\ZipException
  205. * @expectedExceptionMessage Invalid encryption method
  206. */
  207. public function testSetEncryptionMethodInvalid()
  208. {
  209. $zipFile = new ZipFile();
  210. $encryptionMethod = 9999;
  211. $zipFile->setPassword('pass', $encryptionMethod);
  212. $zipFile['entry'] = 'content';
  213. $zipFile->outputAsString();
  214. }
  215. public function testEntryPassword()
  216. {
  217. $zipFile = new ZipFile();
  218. $zipFile->setPassword('pass');
  219. $zipFile['file'] = 'content';
  220. self::assertFalse($zipFile->getEntryInfo('file')->isEncrypted());
  221. for ($i = 1; $i <= 10; $i++) {
  222. $zipFile['file' . $i] = 'content';
  223. if ($i < 6) {
  224. $zipFile->setPasswordEntry('file' . $i, 'pass');
  225. self::assertTrue($zipFile->getEntryInfo('file' . $i)->isEncrypted());
  226. } else {
  227. self::assertFalse($zipFile->getEntryInfo('file' . $i)->isEncrypted());
  228. }
  229. }
  230. $zipFile->removePasswordEntry('file3');
  231. self::assertFalse($zipFile->getEntryInfo('file3')->isEncrypted());
  232. self::asserttrue($zipFile->getEntryInfo('file2')->isEncrypted());
  233. $zipFile->removePassword();
  234. $infoList = $zipFile->getAllInfo();
  235. array_walk($infoList, function (ZipInfo $zipInfo) {
  236. self::assertFalse($zipInfo->isEncrypted());
  237. });
  238. $zipFile->close();
  239. }
  240. /**
  241. * @expectedException \PhpZip\Exception\ZipException
  242. * @expectedExceptionMessage Invalid encryption method
  243. */
  244. public function testInvalidEncryptionMethodEntry()
  245. {
  246. $zipFile = new ZipFile();
  247. $zipFile->addFromString('file', 'content', ZipFileInterface::METHOD_STORED);
  248. $zipFile->setPasswordEntry('file', 'pass', 99);
  249. }
  250. public function testArchivePasswordUpdateWithoutSetReadPassword()
  251. {
  252. $zipFile = new ZipFile();
  253. $zipFile['file1'] = 'content';
  254. $zipFile['file2'] = 'content';
  255. $zipFile['file3'] = 'content';
  256. $zipFile->setPassword('password');
  257. $zipFile->saveAsFile($this->outputFilename);
  258. $zipFile->close();
  259. self::assertCorrectZipArchive($this->outputFilename, 'password');
  260. $zipFile->openFile($this->outputFilename);
  261. self::assertCount(3, $zipFile);
  262. foreach ($zipFile->getAllInfo() as $info) {
  263. self::assertTrue($info->isEncrypted());
  264. }
  265. unset($zipFile['file3']);
  266. $zipFile['file4'] = 'content';
  267. $zipFile->rewrite();
  268. self::assertCorrectZipArchive($this->outputFilename, 'password');
  269. self::assertCount(3, $zipFile);
  270. self::assertFalse(isset($zipFile['file3']));
  271. self::assertTrue(isset($zipFile['file4']));
  272. self::assertTrue($zipFile->getEntryInfo('file1')->isEncrypted());
  273. self::assertTrue($zipFile->getEntryInfo('file2')->isEncrypted());
  274. self::assertFalse($zipFile->getEntryInfo('file4')->isEncrypted());
  275. self::assertEquals($zipFile['file4'], 'content');
  276. $zipFile->extractTo($this->outputDirname, ['file4']);
  277. self::assertTrue(file_exists($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'));
  278. self::assertEquals(file_get_contents($this->outputDirname . DIRECTORY_SEPARATOR . 'file4'), $zipFile['file4']);
  279. $zipFile->close();
  280. }
  281. }