文字列の暗号化
文字列の暗号化とは、PreEmptive Protection™ DashO™ for Android & Java が処理されたクラスの定数プール内の文字列を暗号化された値に置き換え、その後実行中のアプリケーション内で復号するプロセスであり、コードの静的解析によって文字列定数を読み取ることをより困難にするものです。 これにより、機密事項に関連する文字列に保護レイヤーが提供される一方で、ソフトウェアが解析し難くなります。 たとえば、文字列の暗号化を使用した場合、攻撃者は特定のメッセージの使用箇所を特定するために、そのメッセージの文字列定数を簡単には特定できなくなります。
文字列の暗号化は、DashO GUI の String Encryption - Options ページで有効または無効にしたり構成したりできます。
文字列の暗号化で除去を使用する
文字列暗号化は単独で、ほとんどの文字列を保護しますが、インラインの文字列定数は必ずしも完全に保護されるとは限りません。 Java コンパイラは文字列定数を行内で展開し、その文字列が使用される場所に効果的にコピーします。 DashO は元のフィールド値を暗号化しません。暗号化すると、間違った動作を引き起こす可能性、たとえば、外部アプリケーションによって使用されるバイナリの API 定数の値を壊したりするなどの可能性があるためです。
つまり、一部の文字列定数は、文字列の暗号化後もその場に暗号化されていない状態で残るということです。 これらの文字列定数は、外部アプリケーションによって使用されない場合には、安全に除去することができます。 したがって、それらの文字列定数を保護するには、使用されていないメンバーを除去するように DashO を構成します。 インラインの文字列定数参照は、定義フィールドを "used" としてマークしません。
ライブラリの場合は Remove if not public
を指定し、それ以外の場合は Remove
を指定します。
Remove if not public
を使用する場合には、パブリック文字列は除去されないため、保護が必要な文字列はパブリックにしないでください。
これらの設定が影響する範囲は、除去の対象からクラス、メソッド、またはフィールドを除外することで調整できます。
また、文字列の暗号化を使用する場合はサイズとパフォーマンスのコストがかかるため、暗号化の対象からメソッドやクラスを除外する必要がある可能性があります。 インラインがある場合は、文字列定数の文字列のすべてのコピーを暗号化するために、文字列定数を定義するクラスと、文字列定数を参照するすべてのクラスの両方を文字列の暗号化で保護してください。
メモ:
DashO の除去機能/処理は、R8 で扱われるため、Android モードでは利用できません。 Android モードを使って文字列定数を完全に保護しようとしている場合は、R8 を有効化しておきます。
Android モードでの文字列の暗号化とリフレクション
Android モードでは、名前変更と除去が R8 によって処理されるのに対し、文字列の暗号化は DashO によって処理されます。 R8 は単独で、リフレクションを介してアクセスされたクラスを検出すると共にそれらのクラスを名前変更と除去の対象から除外することができます。
ただし、DashO の文字列暗号化機能では、R8 が、文字列リテラルに含まれるクラス名を認識しないようにすることができます。 これにより、R8 がリフレクションを介して読み込まれたクラスを除去したり名前変更したりするため、実行時にエラーが発生します。 このようなエラーの発生を防止するには、以下のいずれかを行います。
- リフレクションを介して読み込まれたクラスが除去されたり名前変更されたりしないようにするため、R8
-keep
規則を追加します。 - リフレクション呼び出しによって読み込まれたクラスが R8 によって検出されるように、リフレクション呼び出しが記述されているメソッドを文字列の暗号化対象から除外します。
また、R8 がそれらのクラスを名前変更して文字列リテラルを適切に更新できるように、R8 で
-adaptclassstrings
を使用することもできます。
構成
以下の設定は、DashO GUI の String Encryption - Options ページで構成することができます。
メモ:
文字列の暗号化の対象選択規則または対象除外規則をメソッド レベルで構成している場合、別の規則を持つメソッドによって再使用される文字列は期待どおりに暗号化されない場合があります。
文字列の暗号化レベル(String Encryption)
文字列の暗号化レベル(1 ~ 10)は、暗号化アルゴリズムと復号アルゴリズムの強度とパフォーマンスを制御するものです。 レベルが高いほど暗号化の強度も高くなりますが、復号の実行時間が長くなるのでアプリケーションの速度が低下する可能性があります。 既定のレベルは "2" です。
復号メソッドの数(Decrypters)
各出力に含まれるクラスに対して生成、追加される復号メソッドの数を制御できます。 復号メソッドの名前と署名はランダムに選択されます(入力割り当てファイルを使用する場合を除く)。 既定の復号メソッド数は "2" です。
メモ:
マージされていない出力では、作成される復号メソッドの数は、入力の数だけ乗じられます。 復号メソッドをグローバルに(復号が使用される jar ファイルの内部に保持するのではなく)配置したい場合は、INJECT_DECRYPTERS_GLOBALLY
という名前のユーザー プロパティ を追加し、それをtrue
に設定します。 このプロパティを設定すると、構成された数の復号メソッドが、各出力に追加されるのでなく、出力間に分散されます。
復号メソッドは、Android モードでは常にグローバルに配置されます。
復号クラス(Decrypter Class)
生成された静的な匿名内部クラスの外部クラスとして機能する、復号メソッドが格納されるクラスを制御できます。 このようなクラスについて、以下の条件を指定できます。
- これらのクラスの選択元にすることができないパッケージ
- これらのクラスが満たさなければならない、
public
などの修飾子 - クラスの名前が一致しなければならない正規表現、グロブ(glob)パターン、名前
既定では、DashO により、java.
、javax.
、android.
パッケージがすべて除外され、public
クラスのみが選択されます。
メモ:
名前の条件を指定すると、復号メソッドはその条件に基づいて差し込まれ、jar のバウンダリに関係なく使用されます。
文字列の暗号化割り当てファイル
増分難読化を使用する場合は、最初の難読化が行われたときに使用された復号メソッドを DashO が再生成できる必要があります。 再生成できない場合は、難読化された新しいコードが、以前に難読化されたコードと正しく相互運用できなくなる可能性があります。 以前の DashO 実行において配置された復号メソッドと、それらの復号メソッドが配置された場所を記録するには、文字列の暗号化割り当てファイルを使用します。
入力割り当てファイルの場所と出力割り当てファイルの場所は、DashO GUI の String Encryption - Options ページで指定できます。 出力割り当てファイルの場所を指定すると、DashO により、そのビルド時に生成される復号メソッドについての情報が含まれた、文字列暗号化割り当てファイルが生成されます。 入力割り当てファイルを指定した場合は、DashO により、その割り当てファイル内に指定された文字列復号メソッドが生成されると共に、文字列の暗号化レベルと復号メソッドの数の設定が無視されます。
メモ:
文字列の暗号化割り当てファイルは Android モードではサポートされていません。
対象選択と対象除外
文字列の暗号化を適用する場所を決定する規則を設定できます。 文字列の暗号化は、サイズと実行時のパフォーマンスというコストがかかるので、アプリケーションのうち、機密性の高い部分だけに適用するとよいでしょう。 文字列暗号化対象の選択と除外は、DashO GUI の String Encryption - Include および String Encryption - Exclude ページで指定できます。 対象選択を指定しない場合、文字列暗号化は対象除外規則に含まれていないすべてのメソッドに適用されます。 対象選択を設定した場合、文字列の暗号化は対象として選択されたメソッドにのみ適用されます。
カスタム暗号化
DashO が既定の文字列暗号化の代わりに使用できるように、カスタム暗号化メソッドとカスタム復号メソッドを指定することができます。 詳細については、カスタム暗号化を参照してください。