前回ビット演算を紹介した。
ビット演算にはANDとORのほかにも色々あり、そのうちのひとつがXOR(排他的論理輪:はいたてきろんりわ)である。
これは、与えられた2つのビットのうち、どちらか片方が1でもう片方が0のときに、1になる。
全ケース書き出すと、以下のようになる。
1 Xor 1 = 0
1 Xor 0 = 1
0 Xor 1 = 1
0 Xor 0 = 0
このXOR演算には、あるビット列Aに対し、別のビット列BをXor演算させると暗号化され、もう一度ビット列BをXorさせると元のビット列Aにもどる性質がある。
文書ではよく分らないと思うのでやってみよう。
ビット列A | 11110000 |
ビット列B | 01010101 |
Xor結果 | 10100101 |
Xor結果を仮に、ビット列Cとしておこう。
ビット列C:10100101
ビット列Cから、元のビット列Aは推測できない。
しかし、ビット列Cにもう一度ビット列BをXORしてやると、ビット列Aにもどる。
ビット列C | 10100101 |
ビット列B | 01010101 |
Xor結果 | 11110000 |
この性質を利用した暗号化が、XOR暗号である。
平文にパスワードをXorすると暗号文が得られる。
暗号文にもう一度パスワードをXorすると復号化できるという原理だ。
VBAで再現したのがこちら
Sub XOR暗号サンプル() '■平文とパスワードを準備 平文 = "これは平文です。" パスワード = "pass" '■パスワードを平文の長さに切りそろえ Do While Len(平文) > Len(パスワード) パスワード = パスワード & パスワード Loop パスワード = Left(パスワード, Len(平文)) '■暗号文を出力 暗号文 = "" For i = 1 To Len(平文) 暗号文 = 暗号文 & CStr(Asc(Mid(平文, i, 1)) Xor Asc(Mid(パスワード, i, 1))) & " " Next Debug.Print "暗号文は:" & 暗号文 '■復号化された平文を出力 暗号配列 = Split(暗号文, " ") 復号文 = "" For j = LBound(暗号配列) To UBound(暗号配列) - 1 復号文 = 復号文 & Chr(CLng(暗号配列(j)) Xor Asc(Mid(パスワード, j + 1, 1))) Next j Debug.Print 復号文 End Sub
※解説用なので変数は宣言せずに使用しています。実際に利用される場合は変数宣言してください。
まず、平文とパスワードの長さを揃えておく。
パスワード長が平文の長さに達するまで足し合わせて、それからLeftで切り揃えている。
それから、平文とパスワードから一文字ずつ取り出し、Asc関数で文字コードに変えてからXorしていく。
それをスペース区切りで足し合わせたものを暗号文とし、解読の前にはスペースでSplitして暗号配列としておく。
そして暗号配列とパスワードから一文字ずつ取り出しながら、Xorして平文の文字コードを得て、Chr関数で文字に戻していく。
最後に、つなぎ合わせた復号文を表示させて完了。
以前に紹介したシーザー暗号は、それ単体で解読されてしまう危険をはらんでいるが、XOR暗号はパスワードがバレない限り、シーザー暗号よりは安全である。
thom.hateblo.jp
ただし、パスワードを推測する方法は存在するのでこちらも簡易暗号程度に考えておこう。
関連記事
ビット演算の応用で、2つの画像の差分を取り出すマクロを紹介しています。
thom.hateblo.jp