1

これは、世界中のすべての暗号学者からの助けを求める叫びです。

シナリオ: 一部のパスワードを XML ファイルに保存する Windows アプリケーション (おそらく VC++ または VB でビルドされ、その後 .Net に移行されたもの) があります。passwordを指定するA0123456789abcDEFGHと、結果の「暗号化された」値は次のようになります。04077040940409304092040910409004089040880408704086040850404504044040430407404073040720407104070

文字列を見ると、これは単なる文字シフトであることがわかりました。「04」は実際の文字値を区切ります。これは 10 進数です。これらの値を 142 から差し引くと、元の ASCII コードが返されます。Jython (2.2) では、私の復号ルーチンは次のようになります (コメントの提案のおかげで編集されました)。

blocks = [ pwd[i:i+5] for i in range(0, len(pwd), 5) ] 
# now a block looks like '04093'
decrypted = [ chr( 142 - int(block[3:].lstrip('0')) ) for block in blocks ]

これは ASCII 値 (合計 127) と少数のアクセント付き文字には問題ありませんが、8 ビット文字セットにはさらに 128 文字あります。受け入れられる値を 142 に制限することは、10 進数の観点からは意味がありません。

編集: システムをくまなく調べたところ、3 つの非 ASCII 文字が見つかりました。

è 03910
Ø 03926
Õ 03929

これらの値から、実際に 4142 から 4 桁のブロックを減算すると (区切り文字として「0」のみを残す)、正しい文字が得られるように見えます。

だから私の質問は:

  • Windows の世界でこの種の難読化スキームに精通している人はいますか? これは標準ライブラリ関数の製品でしょうか? 正直に言うと、私は Win32 と .Net の開発にあまり詳しくないので、非常に単純なものを見落としている可能性があります。

  • それがライブラリ関数でない場合、魔法の 142 番号に頼らずにこれらの値の難読化を解除するより良い方法、つまり、ASCII 以外の文字を特殊なケースに入れずに実際に適用できるスキームを考えられますか? 私はビットシフトなどすべてが苦手なので、訓練された目に明らかな何かを見落としている可能性があります。

4

1 に答える 1

2

Windows の世界でこの種の難読化スキームに精通している人はいますか?

正しく理解すれば、ROT13のような単純な回転暗号です。

なぜ誰もがこれを使用するのでしょうか?

まあ、一般的に、これは非常に一般的です。難読化する必要があるデータがあるとします。ただし、復号化アルゴリズムとキーは、視聴者が持っているソフトウェアに組み込まれている必要があります。AES のような手の込んだものを使用しても意味がありません。なぜなら、AES をクラックする代わりに、誰かがアルゴリズムを掘り下げて、コードからキーを取り出すことができるからです。隠された鍵を見つけるよりもクラックするのがわずかに難しい暗号化スキームは、完全な暗号化スキームと同じくらい優れています。(多くの場合、停止することについて本当に心配することさえありませんただし、攻撃者が契約上または法律上の理由で悪意を持って行動したに違いないという事実の後に証明することについて.) したがって、単純なローテーション暗号または単純な xor 暗号のいずれかを使用します。高速で、間違いにくく、簡単です。最悪の場合は、手動で復号化して破損したデータを回復することもできます。

詳細については:

ASCII 以外の文字を処理したい場合は、ほぼ Unicode を使用する必要があります。固定の 8 ビット文字セットまたはローカル システムの OEM 文字セットを使用すると、他のマシンからのパスワードを処理できなくなります。

Python スクリプトでは、ほぼ確実に Unicode 文字を処理します。Python では、 でバイト単位str、または で Unicode 文字を処理するためunicodeです。WCHAR *ただし、Windows ネイティブ API は UTF-16-LE コード ポイント(別名 16 ビット ワードの文字列) を扱うため、Windows C または .NET アプリは UTF-16 を使用する可能性がはるかに高くなります。

では、なぜ 4142 なのか? まあ、キーが何であるかは問題ではありません。一部のプログラマーが42を提案したと思います。彼のマネージャーは、「それはあまり安全ではないようだ」と言った。彼はため息をつき、こう言った。「なぜ、どの鍵よりも安全な鍵がないのかは、すでに説明した...わかっているだろうが、忘れてほしい。4142 はどうだろうか?」マネージャーは、「ああ、それは本当に安全な番号のようですね!」と言いました。それが4142の理由です。


ライブラリ関数でない場合は、魔法の 142 番号に頼らずにこれらの値の難読化を解除するためのより良い方法を考えてください。

魔法の 4142 に頼る必要がありますが、これをもっと簡単にすることができます。

def decrypt(block):
    return struct.pack('>H', (4142 - int(block, 10)) % 65536)

したがって、5 文字の各ブロックは、C unsigned-short ラップアラウンド規則を使用して、4142 から減算された UTF-16 コード単位の 10 進数表現です。

これをネイティブの Windows C で実装するのは簡単ですが、Python では少し難しくなります。私が思い付くことができる最高の変換関数は次のとおりです。

def decrypt_block(block):
    return struct.pack('>H', (4142 - int(block, 10)) % 65536)

def decrypt(pwd):
    blocks = [pwd[i:i+5] for i in range(0, len(pwd), 5)] 
    return ''.join(map(decrypt_block, blocks)).decode('utf-16-be')

これは C や C# ではもっと些細なことで、おそらく彼らが実装したものなので、私が何をしているのか説明させてください。

文字列を 5 文字のブロックのシーケンスに変換する方法は既に知っています。

int(block, 10)はあなたのと同じことをしていますint(block.lstrip('0')).'0'接頭辞がPythonにそれを10進数ではなく8進数として扱わせないようにしますが、より明示的にします. Jython 2.2 ではこれが実際に必要だとは思いません (最新の Python/Jython では絶対に必要ではありません) が、念のため残しました。

次に、C では、unsigned short x = 4142U - y;自動的に適切にアンダーフローする を実行するだけです。Python にはunsigned short値がなく、 signed だけintなので、アンダーフローを手動で行う必要があります。(Python は床除算と剰余を使用するため、符号は常に除数と同じです。これは C では当てはまりません。少なくとも C99 とほとんどのプラットフォームの C89 では当てはまりません。)

次に、C では、unsigned short を 16 ビットの「ワイド文字」にキャストします。Python にはそれを行う方法がないため、 を使用する必要がありますstruct.pack。(これをビッグ エンディアンに変換していることに注意してください。これは、デバッグが容易になるためです。C では、ネイティブ エンディアンに変換します。これは Windows であるため、リトル エンディアンになります。)

これで、2 文字の UTF-16-BE コード ポイントのシーケンスが得られました。joinそれらを 1 つの大きな文字列にまとめdecodeてから、UTF-16-BE にします。


私がこれを正しく理解していることを本当にテストしたい場合は、非 ASCII だけでなく、非西洋文字を見つける必要があります。特に、次のものが必要です。

  • > U+4142 で < U+10000 のキャラクター。U+7000 (瀀) のようなほとんどの CJK 表意文字は、この条件に適合します。'41006'4142-0x7000 が unsigned short としてロールオーバーされるため、これは のように表示されます。
  • >= U+10000 のキャラクター。これには、一般的ではない CJK 文字、特殊な数学文字、古代のスクリプトの文字などが含まれます。4142-0xd800=14382、および 4142-0xdf00=12590 なので、'1438212590'.

1 つ目は見つけるのが難しく、私が扱ったほとんどの中国語および日本語ネイティブのプログラマーでさえ ASCII パスワードを使用しています。2 つ目は、なおさらです。歴史言語学の教授以外は、パスワードに古風なスクリプトを使用することを考えることさえあるでしょう。マーフィーの法則により、正しいコードを記述した場合は決して使用されませんが、そうでない場合は、コードを出荷するとすぐに表示されることが保証されています。

于 2013-09-17T18:56:49.947 に答える