DjangoBrothers BLOG

2019/06/29

このエントリーをはてなブックマークに追加
Python デプロイ

PyArmorでPythonのコードを難読化する

特定のプロジェクトでは、Pythonで書いたコード(スクリプトやSDK)の全体や一部を、人間に読みづらい形に変換して保護したい場合があります。 その際に利用できるPyArmorというパッケージを紹介します。

難読化とはなにか?

プログラムの内容を人間が読みづらい状態にすること難読化といいます。

組み込み式のツールに含まれるプログラムのソースコードを他社に盗まれないようにしたり、特別なアルゴリズムを持たせたコードの部分だけをうまく隠しながらスクリプトファイルなどをクライアントに納品したい場合に利用します。

難読化には、単純に読みづらいコードをあえて書くといった方法もありますが、今回説明するのは基本的に、コードのリバースエンジニアリングが不可能な状態にするというところを目指すものです。

蛇足ですが、特定の要件を満たすコードをいかに難しく/美しく書けるか、といった一種の遊びの要素なども含まれることもあります。 難読化コード(Wikipedia)

クラウドサービスを使えば良い?

難読化などの手法を使う前に、そもそもソースコードを読ませないようにするという手もあります。クラウドサービスなどでサービスを提供すれば、基本的にはコードを解析されることはありません。(HTMLやCSSなどのフロントエンドのコードは別ですが)

例えば、GoogleやAmazon Web Serviceなどのサービスでは、ウェブ上から簡単にAPIで様々な機能を利用できますが、その中身のソースコードがどうなっているかはユーザー側にはわかりません。(一部オープンソースのプロジェクトなどもあります)

概念的にはクラウドサービスとは少し異なりますが、みなさんが普段使っているwebサービスもソースコードまではわかりませんよね。

このようにそもそもソースコードのレイヤーに外部の人を触れさせないというのが一番簡単かつ確実ですが、どうしてもコードを直接提供する必要がある場合も存在します。

例えば、組み込み式のSDKを提供する場合や遅延を少しでも遅くしたい場合などはこれに当てはまります。

この場合、他社やユーザーにソースコードを解析されると、技術を盗まれたり、セキュリティ面での弱みを突かれたりするなど、問題があります。

そのため、難読化などを施してソースコードを守るようにするのです。

PyArmorとは?

Pythonでのプロジェクトを難読化する際のおすすめのパッケージとしてPyArmorがあります。

PyArmorとは、コマンドライン経由で簡単にPythonベースのソフトウェアをセキュアなパッケージに変換でき、エンタープライズ向けの機能も提供しています。

PyArmorの特徴は主に以下の3つです。

  • 通常のPythonプロジェクトと同じように使うことができる
  • ソースコードの復元が実質的に不可能
  • ファイルの実行期限や実行環境の制限を設けることができる

PyArmorで生成したファイルは、通常のPythonのパッケージと同じように使うことができます。また、単一のファイルだけでなく、プロジェクト単位でまとめることができるため、普段使っているままの形で難読化後のファイルをクライアントに提供することができます。

また、難読化という作業は、単純に読みづらくするくらいでは頑張れば復元できたりします。しかし、PyArmorではC言語でコンパイルされたランタイムファイルを生成し、それをもとに処理を実行するため、仮にリバースエンジニアリングをするにしても現実的な時間では実現できません。

3つ目の特徴の「ファイルの実行期限を決めることができる」というのはビジネス上の重要なポイントで、例えば、あるSDKを期限付きのライセンスで提供する場合などに重宝します。(e.g. 1年間しか使えない契約のSDKをクライアントに提供する) 単純に難読化するだけではなく、ビジネスに利用する場合にも活躍する機能です。

使い方

今回はPyArmorの基本的な使い方を紹介します。 実際に利用するファイルをrun.pyとします。

まずはPyArmorをインストールしましょう。PIPでインストールできます。

PyArmorをインストール

$ pip install pyarmor

PyArmorのobfuscateコマンドで難読化します。

難読化を実行

$ pyarmor obfuscate run.py

この操作で/distというフォルダが作成され、以下のファイルが生成されます。(Macで操作した場合のファイルです) run.pyファイル以外の新しく生成されたファイルたちをランタイムファイルと呼びます。

  • _pytransform.dylib: 実行時に使用されるダイナミックライブラリ(Macだと.dylibファイル、Linuxだと.soファイル)
  • license.lic: ライセンスファイル、有効期限を設定できる(デフォルトは無期限)
  • pytransform.key: データファイル、実行キーを保持
  • pytransform.py: 他のランタイムファイルを呼び出して実行するファイル
  • run.py: 難読化されたファイル

難読化されたファイルはこのようになっています。実際のrun.pyファイルの中身は秘匿化されて、その他のランタイムファイルを呼び出すだけになっています。

dist/run.py

from pytransform import pyarmor_runtime
pyarmor_runtime()
__pyarmor__(__name__, __file__, b'\x6c\xd0\ ... x00', 1)

run.pyファイルは通常の使い方と同じで、他のファイルからインポートして利用できます。

ライセンス期限を設ける

前述の通り、PyArmorで難読化したコードに対してライセンス期限を設けることができます。 コードの難読化時に作成された、license.licファイルには、このパッケージのライセンス情報が記載されています。このファイルを期限付きのライセンスに置き換えることで、ランタイムファイルに実行期限をつけることができます。

以下のコマンドでライセンスファイルを作成します。

2020年8月1日まで利用できるライセンスを作成

$ pyarmor licenses --expired 2020-08-01 license_exp20200801

このコマンドによりlicenses/license_exp20200801/というフォルダが作成され、その中にlicense.liclicense.lic.txtというファイルができます。license.lic.txtの方にはライセンス期限の情報が記載されています。license.licは先ほど難読化した際に生成されたファイルと同様のもので、こちらのファイルを置き換えることで、ライセンス期限を設定できます。

注意点

PyArmorの難読化は、難読化したOS環境に合わせてランタイムファイルが作成されますが、実際にそのファイルを実行する環境が難読化したOS環境と異なる場合にはきちんと動きません。

そのため、各環境に合わせたファイルをダウンロードする必要があります。

例えば、Macで難読化を実行したファイルをLinuxやWindowsで利用したい場合には、こちらから各プラットフォーム用のダイナミックライブラリをダウンロードして置き換える必要があります。

参考