バイナリ変換してXORして遊びたい
暗号技術入門を呼んでいると、XORがバンバン出てくるので、ちょっとやってみようと思い立った
ruby で計算するのが早い
>> "Hello".each_byte.map{|e| e }.join(" | " ) => "72 | 101 | 108 | 108 | 111" >> "Hello".each_byte.map{|e| sprintf("%b", e) }.join(" | " ) => "1001000 | 1100101 | 1101100 | 1101100 | 1101111"
これをXORと併せて計算しましょう
本当は、C言語のプログラミングの授業でやりたいんだけどねぇ。
Ruby で ランダムパッドをして遊ぶ。
>> "Hello".each_char.zip( "World".each_char ) => [["H", "W"], ["e", "o"], ["l", "r"], ["l", "l"], ["o", "d"]] >> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] } => [31, 10, 30, 0, 11] >> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] } => [31, 10, 30, 0, 11] >> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] }.zip("World".each_byte).map{|e| e[0] ^ e[1] }.map(&:chr).join => "Hello" >>
Hello を World で XORで符号化する
>> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] }.map{|e| sprintf("%08b", e) }.join(" | " ) => "00011111 | 00001010 | 00011110 | 00000000 | 00001011"
この結果を、World以外の文字列でXORするともとに戻らない。
>> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] }.zip("abcdef".each_byte).map{|e| e[0] ^ e[1] }.map(&:chr).join => "~h}dn"
ただし、ただし、一部が一致すると。。。
>> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] }.zip("world".each_byte).map{|e| e[0] ^ e[1] }.map(&:chr).join => "hello" >>
このように、一部が一致するとXORのランダムパッドでは暗号とは言えなくなる。
出てきた文字が正しいかわからない
>> "Hello".each_byte.zip( "World".each_byte ).map{|e| e[0] ^ e[1] }.zip("XYZaa".each_byte).map{|e| e[0] ^ e[1] }.map(&:chr).join => "GSDaj"
ここでは、暗号化に使う鍵に、「World」という文字列を採用しましたが、ランダムの使い捨てパッドである必要があります。
こうやって扱ってみると、ランダムパッドによる使い捨て暗号は、色々と問題があることがわかる。