08 March 2012

(Linux) unzipで解凍できないAES方式パスワード付きzipファイル

パスワードをつけて圧縮したファイルを、別のパソコンで解凍しようとしたところ、解凍できない…

zipコマンドで未対応の暗号化形式の場合のメッセージ形式の例
$ unzip unknown_encode.zip 
Archive:  unknown_encode.zip
   skipping: test1.txt           unsupported compression method 99
$ unzip unknown_encode.zip 
Archive:  unknown_encode.zip
   skipping: test1.txt           need PK compat. v5.1 (can do v4.6)

これはコマンドラインで実行した結果だが、実際はGnomeデスクトップ上の書庫マネージャーを使っている。出てくるメッセージは同じもの。

Windows 10なら次のような表示になる

20200112-win10-1ipaes128.jpg

ファイルが壊れているわけではない

コマンドラインで詳しく調べてみると

$ zipinfo -v unknown_encode.zip 
Archive:  unknown_encode.zip   6664 bytes   2 files
 
End-of-central-directory record:
-------------------------------
 
  Actual offset of end-of-central-dir record:        6642 (000019F2h)
  Expected offset of end-of-central-dir record:      6642 (000019F2h)
  (based on the length of the central directory and its expected offset)
 
  This zipfile constitutes the sole disk of a single-part archive; its
  central directory contains 2 entries.  The central directory is 139
  (0000008Bh) bytes long, and its (expected) offset in bytes from the
  beginning of the zipfile is 6503 (00001967h).
 
  There is no zipfile comment.
 
Central directory entry #1:
---------------------------
 
  playlists.xml
 
  offset of local header from start of archive:     0 (00000000h) bytes
  file system or operating system of origin:        Unix
  version of encoding software:                     2.0
  minimum file system compatibility required:       Unix
  minimum software version required to extract:     2.0
  compression method:                               unknown (99)
  file security status:                             encrypted
  extended local header:                            no
  file last modified on (DOS date/time):            2012 Mar 7 07:38:02
  32-bit CRC value (hex):                           00000000
  compressed size:                                  358 bytes
  uncompressed size:                                1248 bytes
  length of filename:                               13 characters
  length of extra field:                            11 bytes
  length of file comment:                           0 characters
  disk number on which file begins:                 disk 1
  apparent file type:                               binary
  Unix file attributes (100644 octal):              -rw-r--r--
  MS-DOS file attributes (20 hex):                  arc 
 
  The central-directory extra field contains:
  - A subfield with ID 0x9901 (unknown) and 7 data bytes:
    02 00 41 45 01 08 00.
 
  There is a local extra field with ID 0x5855 (old Info-ZIP Unix/OS2/NT) and
  8 data bytes (GMT modification/access times only).
 
  There is no file comment.
$ file unknown_encode.zip 
unknown_encode.zip: Zip archive data, at least v5.1 to extract

どうも圧縮手法がunzip version 5.1未満では対応していない方式らしい…

Googleで検索すると、ZipCrypto, AES-128, AES-192, AES-256 方式で暗号化されるらしく、Ubuntuにインストールされているunzip (version 2やversion 3)はZipCryptoしか対応していないようだ。

ということで、p7zip, p7zip-fullパッケージをインストールすると、ちゃんと解凍できるようになる。

$ 7z t unknown_encode.zip 
 
7-Zip 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=ja_JP.UTF-8,Utf16=on,HugeFiles=on,4 CPUs)
 
Processing archive: unknown_encode.zip
 
Testing     test1.txt
Enter password (will not be echoed) : ******
 
Testing     test2.txt
 
Everything is Ok
 
Files: 2
Size:       77568
Compressed: 6664

つまり…、p7zipがインストールされているUbuntuの書庫マネージャでは、ZIPを作成するときにp7zipが用いられているようだ。

zipの暗号化方式を制御する

7zipの詳細マニュアルが /usr/share/doc/p7zip-full/DOCS/MANUAL/switches/method.htm に格納されている。それには、暗号化方式の制御は -mスイッチに続いて

-m (Set compression Method) switch
 
Syntax
  -m
 
  Zip
   Parameter               Default Description
   x=[0|1|3|5|7|9]         5       Sets level of compression.
   m={MethodID}            Deflate Sets a method: Copy, Deflate, Deflate64, BZip2, LZMA, PPMd.
   fb={NumFastBytes}       32      Sets number of Fast Bytes for Deflate encoder.
   pass={NumPasses}        1       Sets number of Passes for Deflate encoder.
   d={Size}[b|k|m]         900000  Sets Dictionary size for BZip2
   mem={Size}[b|k|m]       24      Sets size of used memory for PPMd.
   o={Size}                8       Sets model order for PPMd.
   mt=[off | on | {N}]     on      Sets multithreading mode.
   em={EncryptionMethodID} ZipCrypto    Sets a encryption method: ZipCrypto, AES128, AES192, AES256
   tc=[off | on]           on      Stores NTFS timestamps for files: Modification time, Creation time, Last access time.
   cl=[off | on]           off     7-Zip always uses local code page for file names.
   cu=[off | on]           off     7-Zip uses UTF-8 for file names that contain non-ASCII symbols.
   cp={CodePage}

のように指定するとなっている。

例:ZipCrypto方式で暗号化する場合(最も互換性あり)

ZipCrypto方式 (7zコマンドのデフォルト暗号化形式)
7z a -tzip -p****** output.zip input.txt
7za a -tzip -p****** output.zip input.txt
ZipCrypto方式 (7zコマンドで強制的に指定)
7z a -tzip -p****** -mem=ZipCrypto output.zip input.txt
7za a -tzip -p****** -mem=ZipCrypto output.zip input.txt

例:AES方式で暗号化する場合

AES-128方式 (7zコマンド)
7z a -tzip -p****** -mem=AES128 output.zip input.txt
7za a -tzip -p****** -mem=AES128 output.zip input.txt
AES-256方式 (7zコマンド)
7z a -tzip -p****** -mem=AES256 output.zip input.txt
7za a -tzip -p****** -mem=AES256 output.zip input.txt

例:zipコマンドはZipCrypto方式でしか暗号化できない

ZipCrypto方式 (zipコマンド)
zip -e output.zip input.txt
zip --encrypt output.zip input.txt

どの暗号化方式なのかを表示する

$ 7z l -slt test.zip
  
7-Zip 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=ja_JP.UTF-8,Utf16=on,HugeFiles=on,4 CPUs)
 
Listing archive: test.zip
 
--
Path = test.zip
Type = zip
Physical Size = 19937919
 
----------
Path = 01.pdf
Folder = -
Size = 22551568
Packed Size = 19937787
Modified = 2012-06-22 19:43:06
Created = 
Accessed = 
Attributes = .....
Encrypted = +
Comment = 
CRC = 
Method = AES-128 Deflate
Host OS = Unix
Version = 51

暗号化されたzipファイルをテスト(ベリファイ)する

zipコマンドはZipCrypto方式のみ対応
$ zip --test output_zipcrypt.zip
[output_zipcrypt.zip] input.txt password: ******
test of test.zip OK
 
$ zip --test output_aes128.zip
test of output_aes128.zip FAILED
zip error: Zip file invalid, could not spawn unzip, or wrong unzip (original files unmodified)
7zコマンドはZipCrypto/AES方式すべて対応
$ 7z t output_aes128.zip
 
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=ja_JP.UTF-8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Core(TM) i3-8100T CPU @ 3.10GHz (906EB),ASM,AES-NI)
 
Scanning the drive for archives:
1 file, 1726 bytes (2 KiB)
 
Testing archive: output_aes128.zip
--
Path = output_aes128.zip
Type = zip
Physical Size = 1726
    
Enter password (will not be echoed): ******
Everything is Ok                        
 
Files: 1
Size:       2932
Compressed: 1726

暗号化されたzipファイルを解凍する

unzipコマンドはZipCrypto方式のみ対応
unzip [-P パスワード] output_zipcrypt.zip [-d 解凍先dir]
7zコマンドはZipCrypto/AES方式すべて対応
7z x [-pパスワード] [-o解凍先dir] output_aes128.zip
7za x [-pパスワード] [-o解凍先dir] output_aes128.zip

※パスワードはシェルのログ行に記録されるため、コマンドで指定するのではなく、対話的に入力するほうが安全

WindowsでAES方式のzipファイルを解凍する場合は、7-Zipなどの外部ソフトウエアが必要。