2012-03-29 5 views
-2

私は、各文字をスクランブリングしてテキストファイルを変換するencryptというプログラムを書こうとしています。これは、入力をエンコードするために使用されるコマンドライン引数としてキー(文字列)を指定することによって実現されます。したがって:ハスケル暗号化プログラム

cat txtfile.txt | ./encrypt XXAYSAAZZは、テキストをキーと無限に一致させることによってテキストを暗号化します。

The.. 
XXA.. 
The World... 
XXAYSAAZZ etc.. 
The World is Not Enough etc... 
XXAYSAAZZXXAYSAAZZXXAYS etc... 

および"exclusively-or-ing"対応する文字。

module Main where 
import System 
import Data.Char 

main = do arg1 <- getArgs 
     txt <- getContents 
     putStr((snd (unzip (zip (txt) (cycle(head arg1)))))) 

XOR機能:これまでのところ、私はこれを持っている

cat txtfile.txt | ./encrypt XXAYSAAZZ | ./scramble XXAYSAAZZ 

:しかし、原因XORの性質のために、私は、このことによって、元のテキストを保持することができるようになっていますData.Bitsにあります。

私はxorを何度も試してみましたが、どのようにテキストを解読するのか分かりません。

いくつか考えてください。テキストがしたのであれば

cat txtfile.txt | ./encrypt XXAYSAAZZ 

"Hello World, Goodbye World"それは無限すなわちKEY (XXAYSAAZZ)

"XXAYSAAZZXXAYSAAZZXXAYSAAZ"cat txtfile.txt | ./encrypt XXAYSAAZZ | ./encrypt XXAYSAAZZをテキストに置き換える必要が恩返しをする必要があります

"Hello World, Goodbye World" 

を呼び出す場合それは元の文字列を2回返します。

+0

私は暗号化の仕組みを理解していません。それ以上説明できますか? –

+0

キーは出力のテキストを置き換えるはずですので、cat txtfile.txt | ./encrypt 1235423ここで、テキストファイルのテキストは "Hello World"で "12354231235"とし、cat txtfile.txt | ./encrypt 1235423 | ./encrypt 1235423は "Hello World"を返す – DesiBoyz

+1

@DesiBoyzキーが入力を置き換えた場合、入力を戻す方法はありません。暗号化が1対1のマッピングである場合にのみ、入力を戻すことができます。 –

答えて

5

この

putStr((snd (unzip (zip (txt) (cycle(head arg1)))))) 

はちょうど循環キーの同じ長さの部分でテキストを置き換えます。長さ以外のすべての情報が失われているため、テキストを取得することは不可能です。

暗号化は、それぞれのテキスト文字をペアにしたキー文字(十分な長さを得るためにキーを循環させる)でxorになります。

ようなスキームについて、zipWith機能が意図されて

、ここ

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 

let cypher = zipWith xor text (cycle key) 

しかし、あなたはキーが空であることを確認する必要があり、またはそれは動作しません。 ( - それは削除することが予定されている - これまでのところBitsNumのスーパークラス制約を持っているので、そこにすることはできません)しかし、あなたが解決しなければならない別の問題があると、定義された

instance Bits Char where 

はありません。あなたはBitsインスタンスとタイプにあなたの鍵と平文を変換する必要があるので、最も簡単な方法は、Char

main = do 
    (key:_) <- getArgs 
    if null key 
    then error "encryption key must be nonempty" 
    else do 
     let xkey = map fromEnum (cycle key) 
     plain <- getContents 
     let cypher = map toEnum (zipWith xor xkey $ map fromEnum plain) 
     putStr cypher 
+0

cat txtfile.txt | 。/ XXAYSAAZZを暗号化してテキストを循環キーの同じ長さの部分に置き換え、それをcat txtfile.txtの2回呼び出します。 ./encrypt XXAYSAAZZ | ./encrypt XXAYSAAZZは元の文字列を返すべきです。 – DesiBoyz

+4

これは、それがxorの仕組みです。 –

1

これを正しく理解すれば、ここでxor暗号化をしようとしていますか?ちょうど、私はXORがバイナリ文字列でしか動作しないと信じています。私は、あなたの平文をバイナリとして返す自動ダックタイピングがあるとは思わない。文字列を最初にバイナリに変換してから、それを暗号化するためにキーでxorすることができます。暗号化を解除するには、キーをメッセージテキストとともにxorまたはxorにします。

ここで関数の型シグネチャを見てください。

http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Bits.html

あなたはちょうどそれが平文養うことができません。

3

あなたのコードのEnumインスタンスを使用していることについて、あなたは求めているもの以外のいくつかの問題があります。たとえば、実際に入力にXOR演算を適用することはありません。

putStr . map chr $ zipWith xor (map ord txt) (cycle . map ord $ head arg1) 

鍵がここにあるzipWith、一緒に結合機能を使用して2つのリストをzip圧縮:

はこれにあなたの最後の行を変更してみてください(私はまた、括弧のあなたの極端な侵入を根絶の自由を取りました)。 zipは、 zipWithの特殊ケース(すなわち、 zipWith (,))と考えることができます。

また、内容をXORするには、StringBits a => [a]に変換する必要があります。これはmap ordによって行われ、String[Int]IntのインスタンスはBitsです)に変わります。その後、排他的論理和が行われると、[Int]Stringに変換され、map chrに変換されます。

暗号化に関する限り、暗号化されたテキストを元の平文を復元するために同じプログラム(同じキーを使用して)に戻すだけで済みます。 XORはそれほどクールです。

+0

cat txtfile.txt | 。/ XXAYSAAZZを暗号化してテキストを循環キーの同じ長さの部分に置き換え、それをcat txtfile.txtの2回呼び出します。 ./encrypt XXAYSAAZZ | ./encrypt XXAYSAAZZは元の文字列を返すべきです。 – DesiBoyz

+0

@DesiBoyzはい、それは私が言ったことです。 – bitbucket

+0

@DesiBoyzあなたは、このプログラムが2番目のインスタンスにパイプされたときに元の文字列を返さないと言っていますか? – pat

2

何をあなたのコメントから理解しているのは、ワンタイムパッド暗号化アルゴリズムが必要だということです。ここにVernamの実装があります

Prelude> let vernam p t = zipWith (\a b -> Data.Char.chr $ Data.Bits.xor (Data.Char.ord a) (Data.Char.ord b)) (cycle p) t 
Prelude> vernam "XXAYSAAZZ" "The World is Not Enough" 
"\f0$y\EOT.36>x12y\GS.5z\US674>;" 
Prelude> vernam "XXAYSAAZZ" "\f0$y\EOT.36>x12y\GS.5z\US674>;" 
"The World is Not Enough"