Haskell 中的字符串异或

XORing strings in Haskell

我想编写一个使用 XOR 密码加密文本的程序。这就是我现在拥有的:

-- XORres 2 strings
stringXor :: String -> String -> String
stringXor s t = map chr $ zipWith xor (map ord s) (map ord t)

-- encryption and decryption
encDec :: String -> String -> String
encDec text key = stringXor (take (length text) (cycle key)) text

但是encDec "this is a test" "k"的输出是

  "\US\ETX\STX\CANK\STX\CANK\nK\US\SO\CAN\US"

虽然我期待 1f0302184b02184b0a4b1f0e181f4b

这可能是什么问题?我搜索过类似的问题,但这不是很有帮助。

stringXor s t = map chr $ zipWith xor (map ord s) (map ord t)

您将 chr 映射到 XOR 的结果。这会产生每个 ASCII 值的字符。要将结果显示为十六进制,您将需要找到一个不同的函数来替换 chr 或自己编写一个。

旁注:在密码学中,通常使用 Base64 符号而不是十六进制来编码二进制数据,因为它使用更少的字符(因此内存或网络带宽更少)来表示相同的二进制序列。

问题出在 chr :: Int -> Char。此函数将 Int 转换为相应的字符,但 不是 该数字的十六进制表示形式。

例如,您可以使用 intToDigit :: Int -> Char:

定义效用函数
import Data.Char(intToDigit)

toHex2 :: Int -> String
toHex2 h = map intToDigit [d, m]
    where (d, m) = divMod h 16

那么我们可以将函数实现为:

stringXor :: String -> String -> String
stringXor s t = concatMap toHex2 (zipWith xor (map ord s) (map ord t))

:

import Data.Function(on)

stringXor :: String -> String -> String
stringXor s t = concatMap toHex2 (zipWith (xor `on` ord) s t)

然后我们得到:

Prelude Data.Char Data.Bits> encDec "this is a test" "k"
"1f0302184b02184b0a4b1f0e181f"

注意这里不需要用length,其实没有长度更安全,直接用cycle:

encDec :: String -> String -> String
encDec text key = stringXor (cycle key) text

正在获得1f0302184b02184b0a4b1f0e181f4b:

> "\x1f\x03\x02\x18\x4b\x02\x18\x4b\x0a\x4b\x1f\x0e\x18\x1f\x4b"
"\US\ETX\STX\CANK\STX\CANK\nK\US\SO\CAN\USK"

...这正是您从 encDec 看到的输出(在您的预期输出中似乎是一个简单的复制粘贴错误)。