取引先からパスワード付きExcelファイルが送られてくる場合がある。安全性に配慮された形での受け渡しではあるが、すぐに内容を確認できず不便だ。とは言え、毎回同じパスワードであるならば、自動的に解除して自動処理するようなプログラムを作ることができる。今回は、パスワード付きExcelファイルを自動処理してみよう。
パスワード付きExcelファイルは本当に安全なのか
もうずいぶん前から「メールにパスワード付きZIPファイルを添付して送るのは安全ではない」と言われている。それは、第一に、パスワード付きZIPファイルの解読が比較的簡単であること。第二に、ZIPファイルを添付したメールを第三者が見られるのであれば、そのパスワードが書かれたメールも見られることになるため、パスワードで暗号化する意味がないということが理由だ。
それでは、パスワード付きExcelファイルはどうなのだろうか。ZIPファイルの暗号化は、ZipCryptoとAES-256という二つの方式があるが、ZipCryptoで暗号化された場合は鍵長が96ビットしかなく簡単に解読が可能だ。これに対して、パスワード付きExcelファイルは、AESで暗号化されており、鍵長も十分な長さを指定可能だ。この点で、ZIPファイルの暗号化機能を使うよりは、パスワード付きExcelファイルを使う方が安全と言える。ただし、Excelの古い形式(拡張子が「.xls」のもの)はRC4による暗号化が行われており、高速にパスワードの解析を行う手法が発見されているので注意しよう。
なお、暗号化方式に問題はないものの、同じメールでパスワードを送信するならば、当然、パスワードを付けてないのと同じことになる。この場合、メールでパスワード付きZIPファイルを送るのと全く同じ問題が生じる。そのため、あらかじめ何かしらの別の方法でパスワードをやりとりしておく必要があるだろう。また、パスワードは文字数を長くし、英数を含むようにするなどの対策をしよう。
パスワード付きExcelを読む方法 - msoffcrypto-toolのインストール
それでは、Pythonを使ってパスワード付きExcelファイルを読む方法を紹介しよう。そのために「msoffcrypto-tool」と「openpyxl」というライブラリを利用する。ターミナルで次のようなコマンドを実行してライブラリをインストールしよう。
# Windowsの場合
python -m pip install msoffcrypto-tool openpyxl
# macOSの場合
python3 -m pip install msoffcrypto-tool openpyxl
これは、MicrosoftのOfficeファイルで、パスワード付きのものを読むためのライブラリだ。そのため、Excelだけでなく、WordやPowerPointにも対応している。
パスワード付きExcelを読む方法 - サンプルファイルの準備
なお、今回、簡単なExcelファイルを作り、そこに読み取りパスワードを付けることにする。次のようなExcelファイルを作成して保存しよう。
そして、Excelでファイルを保存する際、オプションボタンを押して、読み取りパスワードを「J6s4mWtO2jlQchy」に設定しよう。
パスワード付きExcelを読む方法 - Pythonのプログラム
それでは、パスワード付きExcelの暗号を解除して、Excelファイルを読み込むPythonプログラムを見てみよう。次のようなプログラムとなる。
import io
import msoffcrypto
import openpyxl as excel
# ファイル名とパスワードの指定 --- (*1)
infile = 'example.xlsx' # 入力ファイル名
password = 'J6s4mWtO2jlQchy' # Excelに設定したパスワード
outfile = 'example_no_password.xlsx' # 出力ファイル名
# パスワード付きExcelファイルを読み込む --- (*2)
decrypted = io.BytesIO()
with open(infile, 'rb') as fp:
msfile = msoffcrypto.OfficeFile(fp)
msfile.load_key(password=password)
msfile.decrypt(decrypted)
# 暗号解除した後ファイルに保存 --- (*3)
with open(outfile, 'wb') as fp:
fp.write(decrypted.getbuffer())
# 保存されたパスワードなしExcelファイルを読み込む --- (*4)
wbook = excel.load_workbook(filename=outfile)
sheet = wbook.active
for row in sheet.values:
if row[0] is None: continue
print(row)
上記プログラムを「read_excel.py」という名前で保存しよう。そして、プログラムを実行するため、ターミナル上にて次のコマンドを実行しよう。