データを守ろう 〜知っておきたい暗号化〜
サイキンソーでバイオインフォマティクスエンジニアをしている翠川です(@Sango6mdr)。
最近、業務でデータやソースコードを暗号化して納品する機会が何件かありました。自分の中での整理を兼ねて「暗号化の基本」+「弊社でどんなときにどんな風に暗号化を使っているのか」まとめました。
暗号化って?
暗号化とは「平文」を「暗号」にすることです。
逆に「暗号」を「平文」にすることはなんと呼ぶでしょうか。
答えは「復号」または「平文化」です。
※「復号化」という表現は正しくないようです。日本語的に復号 "化" というのは確かに変ですね。
用語説明
「平文」
平文とは、暗号化されていない状態のデータ。暗号技術に基づく復号、解読などの操作を行わなくても、そのままで内容を取り扱うことができる状態のデータのことを指す。
引用元:https://e-words.jp/w/%E5%B9%B3%E6%96%87.html
「暗号」
暗号とは、ある情報を特定の決まった人しか読めないように一定の手順に基づいて無意味な文字や符号の列に置き換えたもの。情報の伝送や記録、保存の際、第三者に盗み見られたり改竄されないようにするために作成される。
引用元:https://e-words.jp/w/%E6%9A%97%E5%8F%B7.html
暗号化するときに必要な鍵とは
一般的に「平文」を「暗号」にする際に使用する際、符号を用います。これを「鍵」と呼びます。この鍵は大きく分けて以下の二種類の方式があります。
・「共通鍵暗号」:暗号化時と復号時に同一の鍵を使用する方式
・「公開鍵暗号」:対になる二つの鍵を用いて片方で暗号化、もう一方で復号を行う方式
「公開鍵暗号」は暗号を復号する側で鍵を 2 種類(公開鍵と秘密鍵)作成し、暗号化時に使用する鍵(公開鍵)を暗号化を実行する側へ渡し、暗号化を行います。復号する側は復号時に使用する鍵(秘密鍵)を使用し復号を行います。この時、復号側と暗号化側で受け渡しているのは公開鍵のみなので、仮に事故が発生し公開鍵が外部に流出したとしても、暗号化したデータの復号はできないため「共通鍵暗号」と比べて相対的に安全性が高くなります。
サイキンソーで使用している暗号化
ここまでで暗号化自体が何なのか超基礎的な部分を紹介しました。
弊社で実際に使用している暗号化のツールについて紹介します。
OpenSSL コマンドを使用した暗号化
データ量の問題で物理媒体で納品したいデータがある場合、「生データを直接郵送して郵便事故にあったら大変なので関係者以外見れないようにしたい」という要望が出てくると思います。
そのような場合、最低限、AES-256 による共通鍵暗号化を施しています。
https://www.openssl.org/
https://www.openssl.org/docs/man3.0/man7/crypto.html
https://www.libressl.org/
※ OpenSSL コマンドはオリジナルの OpenSSL と mac OS に標準搭載されている libressl が存在します。基本的な使用方法は一緒ですが、ハッシュ値の計算方法が異なることがあるため注意が必要です。
1. 共通鍵を作成
まず準備として以下のコマンドで共通鍵を作成します。
openssl rand -base64 12
2. 暗号化
history に共通鍵を残したくないため `-pass stdin` オプションを付けて標準入力で鍵を受け取るようにします。
openssl enc -e -aes-256-cbc -pbkdf2 -iter 10000 -in ${input file} -out ${output file} -pass stdin
${password}
3. 復号
以下のコマンドを実行して復号します。
openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -in ${input file} -out ${output file} -pass stdin
${password}
OpenSSL コマンドで指定しているサブコマンドとオプションの解説
「enc」:encrypt (暗号化・復号)する際に使用するサブコマンドです。
「-e」「-d」:暗号化する際は「-e」復号する際は「-d」を指定します。
「-aes-256-cbc」: 暗号アルゴリズムを指定しています。その他使用できるアルゴリズムは「openssl enc -list」で確認できます。
「-pbkdf2 -iter 10000」:「-iter」オプションのマニュアルより
Use a given number of iterations on the password in deriving the encryption key. High values increase the time required to brute-force the resulting file. This option enables the use of PBKDF2 algorithm to derive the key.
と記載されており、回数を多く指定するとブルートフォースへの耐性が高くなるようです。デフォルトは「10000」なので指定しなくても問題ないですが warning が出るので一応指定します。「-iter」を指定するときには「-pbkdf2」も付与する必要があります。
「-in」:入力に使用するファイルを指定するときに使用します。
「-out」:出力先のファイル名を指定します。
Python コードの難読化
Python コードを納品する際、納品先で改変出来ないようにしたい。
でもバイナリ化は動作保証などが大変。
そんなときに弊社で利用実績のあるツールが「PyArmor」です。
このツールの良いところはコード自体を読めなくする(難読化する)だけなので、難読化後も引き続き同じ Python 実行環境でそのまま実行することができます。
https://pyarmor.dashingsoft.com/
https://pyarmor.readthedocs.io/en/latest/index.html
※商用利用は有料版を使用する必要があるなど、制限があるため注意してください。
1. インストール
pip install pyarmor
2. 難読化実行
以下のコマンドを実行すると「myscript.py」自体とその同じ階層の「*.py」を難読化します。
このとき、とくに指定しなければ「myscript.py」と同じ階層に「dist」ディレクトリを作成し、その中に難読化済みのスクリプトを格納します。
※ ここで指定したスクリプト(今回は「myscripts.py」)がコードのエントリースクリプトになります。
pyarmor obfuscate myscript.py
難読化前と後のコードのイメージは以下の通りです。
(例 1)難読化前のスクリプト
(例 2)難読化後のスクリプト
エントリースクリプトには以下のコードが挿入されています。(エントリースクリプト以外にはこちらのコードは含まれません。)
from pytransform import pyarmor_runtime
pyarmor_runtime()
難読化されたスクリプトを実行する際には呼び出し元にこのコードが挿入されている必要があります。
例:エントリースクリプト
from pytransform import pyarmor_runtime
pyarmor_runtime()
__pyarmor__(__name__, __file__, b'\x06\x0f...')
例:その他のスクリプト
__pyarmor__(__name__, __file__, b'\x06\x0f...')
もし「myscript.py」より深い階層の「*py」スクリプトも暗号化したい場合は「--recursive」オプションを付与します。
pyarmor obfuscate --recursive myscript.py
最後に
サイキンソーでは「細菌叢で人々を健康に」というミッションを共に実現する仲間を募集しています。
また、以下のフォームからカジュアル面談をお申し込みいただくことが可能ですので、お気軽にお申し込みください。
その他、Twitter(@Sango6mdr) でも相談を受け付けているのでお気軽に DM などでご連絡ください。
参考
https://kei-sakaki.jp/2013/08/09/encryption-and-decryption/
https://e-words.jp/
https://www.openssl.org/
https://www.openssl.org/docs/man3.0/man7/crypto.html
https://www.libressl.org/
https://qiita.com/akase244/items/4f8936957c910682d1de
https://pyarmor.dashingsoft.com/
https://pyarmor.readthedocs.io/en/latest/index.html