JavaでのZIP暗号化の考察

法務系業務を行うシステムを設計するにあたり、次のような要件がありました。
CSVファイルの暗号化方式として、当初からパスワード付きZIPファイルの使用を検討していたため、ZIP圧縮を使用する前提で調査しました。Excelの暗号化については、別の記事で説明します。
当該システムはJavaEEで構築する前提であったため、Java前提の調査となります。

  1. 機密情報を記載したCSVファイルまたはExcelファイルを暗号化した状態でサーバにアップロードできること。
  2. サーバで暗号化されたCSVまたはExcelファイルをダウンロードできること。
  3. 使用ユーザはWindowsを使用する前提である。ITリテラシは高くない場合があるため、可能な限り簡単な方法で暗号化/復号化できること。

方式を検討するにあたって、ZIPの概要や仕様の把握、ユーザの使用環境であるWindowsでのZIP機能のサポート状況、Java言語でのZIP機能のサポート状況を調査しました。これらを踏まえて、設計方式を決定しました。

前提知識

ZIPの概要

  • ZIPフォーマットは1989年にフィル・カッツ氏が発案し、PKWARE社のPKZIPユーティリティに実装された。その後、ZIPフォーマットの仕様はPKZIP0.9のパッケージに同梱されたAPPNOTE.TXTで初めて公開された。
  • ZIPファイルフォーマットは、オープンフォーマットとして、自由に利用できるようになった。様々なユーティリティー、Windows98以降の各バージョンやMacOS X(v10.3)以降等のメジャーなOSにも組み込まれるようになった。
  • ZIPの当初の暗号化方式は、PKWAREのAPPNOTE.TXT(“6.0 Traditional PKWARE Encryption”)で定義されている。この”Traditional PKWARE Encryption”のことを通称ZipCryptoと呼んでいるが、正式なZipCryptoという仕様や定義はないようです。(圧縮の仕様ではなく暗号化の仕様であることに注意。)
  • 2002年頃に上記のZipCryptoに重大な脆弱性が見つかっている。”6.0 Traditional PKWARE Encryption”を読むと、それほどセキュリティが求められない場合や互換性が求められる場面でのみの使用が推奨されている。
    This form of encryption is considered weak by today’s standards and its use is recommended only for situations with low security needs or for compatibility with older .ZIP applications.
  • 2003年~2004年に、より強力な暗号化方式をWinZipとPKWAREが検討し、AESがサポートされた。
  • AESは公の機関で推奨される「安全性が確認された暗号化アルゴリズム」である。アメリカの場合はNIST、日本の場合はcryptrecで採用されている。(暗号化アルゴリズの安全性の根拠を問われた場合、個人的には「アメリカや日本の公的機関で安全性が確認されています。」と伝えることが多いです。)

WindowsとZIP機能

  • WindowsのZIP機能のサポート状況:
    ※どのバージョンでも前述のZipCryptoを使用している。

    OSバージョン(発売年)パスワードなしパスワード付き
    圧縮解凍圧縮解凍
    Windows XP(2003)
    Windows Vista(2007)
    Windows 7(2009)
    Windows 8(2012)
    Windows 10(2015)

    ※1: なぜVistaから除外されたのかの情報がありませんでした。

  • WindowsのZIP機能がZipCryptoを使う理由:
    Windowsで使われているZIP機能(「圧縮フォルダ」)は、サードパーティー製の機能である。
    2000年頃のWindows XP開発時に組み込まれた機能であり、後続のWindowsでも使用されている。この頃にはZipCryptoの脆弱性の情報やより強力な暗号化の話がなかったため、ZipCryptが採用された。
  • WindowsのZIP機能にAESがサポートされない理由:
    上記の通り、ZipCryptoに脆弱性が発見されて暗号化アルゴリズムにAESが追加されたのは2003年前後ある。その時点では、既に圧縮フォルダの機能の開発は完了し、ライセンス契約を締結した後であったため、AES暗号の機能を追加できなかった。
    当該機能はサードパーティー製であり、Microsoftは積極的な開発を行っていない。精通しているエンジニアもいないため、変更は難しい状態である。そのため、AESに対応する予定はない。
  • Windowsで安全なZIPファイルの作成:
    現状では、上記の通りWindowsでAESを使ったZIP暗号化はサポートされておらず、サポートされる予定もない。WindowsでAESを使ったZIP暗号化を使う場合、7-zip等の圧縮・解凍ツールを別途用意する必要がある。

参考:Why is Windows Compressed Folders (Zip folders) support stuck at the turn of the century?

JavaのZIP圧縮・解凍ライブラリ

ZIP圧縮・解凍を行うためのライブラリはいくつか存在するが、ZIP暗号化が行えるライブラリは現状ではTrueZip, winzipaes, 7-Zip-JBinding, zip4jに限られる。サンプル数やメンテナンスの継続性を考慮し、zip4jを推奨する。

ZipCryptoやAESを使った暗号化を行う場合、圧縮解凍ツールやJavaライブラリの実装の差異によって期待通りに動作しない可能性がある。業務で使用する場合、ツールとZIPライブラリ間で相互に圧縮・解凍(暗号化・復号化)が行えることを確認すべきである。

ライブラリ暗号化可否最新版
(公開年)
サンプル数
[検索キーワード]
備考
JDK標準
(java.util.zip)
不可150,000件
[“java.util.zip” example]
JDK1.1(1997)から最新のJDK11,JDK12でも対応
Apache Commons Compress不可1.19
(2019)
4,000件
[“org.apache.commons.compress.archivers.zip” example]
制限事項に”no support for encryption or multi-volume archives”とあり、ZIP暗号化は未対応。
7z形式の暗号化(パスワード付与)に対応
zt-zip不可1.13
(2018)
300件
[“org.zeroturnaround.zip” example]
TrueZIP
(AES)
7.7.10
(2016)
1,300件
[“de.schlichtherle.truezip” example]
プラガブルに変換処理を行うドライバを構成できる仕組みになっており、”TrueZIP Driver ZIP“ドライバを使ってWinZip AESを使用できる。
winzipaes
(AES-256のみ)
1.0.1
(2012)
170件
[“de.idyl.winzipaes” example]
7-Zip-JBinding
(ZipCrypto/AES)
9.20-2.00beta
(2016)
300件
[“net.sf.sevenzipjbinding” example]
7-zipのJavaラッパーであり、別途7-zipライブラリが必要です。
zip4j
(ZipCrypto/AES)
2.2.2
(2019)
1,800件
[“net.lingala.zip4j” example]
2013から更新が途絶えていたが2019年から更新が再開した。

設計時の方針

  • Windowsで使用できるzip圧縮・解凍機能は、当初からZIP仕様で定義されているZIP暗号化方式(通称ZipCrypt)を使っている。これは、既に脆弱性が発見されており、高いセキュリティが求められる場面で推奨されていない。
  • 互換性を優先するならZipCrypto、セキュリティ強度を優先するならAESを推奨する。AESを選択する場合、Windows標準機能では圧縮・解凍できないため、別途ツールの導入が必要となる。また、サーバ側の処理との互換性の確認も必要である。
  • ZipCryptoを使用する場合、パスワード付きZIPファイルは強度が低いこと、互換性のために使っている、旨をユーザに説明すべきである。パスワードが設定できると、セキュリティ強度が上がったようにユーザが錯覚するため。ではなぜセキュリティ強度が低いものを使わせるのかの理由が必要となるため。
  • セキュリティを担保する別の方式として、CSVではなくExcelに機密情報を記載し、Excelのパスワード保護を使う方法も考えられる。Excel 2016のパスワード保護ではAES256が使われているが、Officeのバージョンによって暗号化の強度が異なるので注意が必要である。
  • AES暗号は電子政府推奨暗号リスト等で安全性が確認された暗号化アルゴリズムである。可能であれば、鍵長さが256ビットであるAES256が推奨される。
  • ZipCryptもAESもパスワードから鍵を生成している。AESのように暗号化アルゴリズが安全であっても、設定するパスワードが単純だと、総当たり攻撃等の方法で簡単に復号できてしまう。使用するパスワードは十分複雑にする必要がある。
  • ユーザがパスワードを手打ちするような運用は避けるべきである。ユーザに負荷がかかり、運用そのものが守られなくなるため。基本はコピペやパスワードリマインダから選択するような運用とし、パスワードは複雑なものにするべきである。
  • OWASPが推奨するパスワードについはてこちらの記事が参考になれば幸いです。
  • Zip暗号化ではZipCrypt/AESに限らず、ファイル名は暗号化されておらず、いつでも参照可能な状態になっている。そのため、ファイル名に機密情報を含めてはいけない。
  • サーバ側でのZIP圧縮・解凍ライブラリとしては、ネット上での情報量やメンテナンスの継続性、ZipCrypto/AESの暗号化に対応するzip4jを推奨する。
  • ZIPファイルを解凍すると数百TB/PB等の巨大なファイルが作成され、コンピュータ資源を枯渇させるZIP BOMBと呼ばれる攻撃がある。イントラネット等のある程度安全性が確保された環境であれば良いが、インターネット向けのアプリの場合は対策が必須となる。
    IDS04-J. ZipInputStream からファイルを安全に展開する