String Haskell中的XORing字符串

String Haskell中的XORing字符串,string,haskell,xor,String,Haskell,Xor,我想写一个用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 =

我想写一个用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“这是一个测试”“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符号来编码二进制数据,而不是十六进制,因为它使用更少的字符(因此更少的内存或网络带宽)来表示相同的二进制序列。

问题在于。此函数用于将
Int
转换为相应的字符,但不是该数字的十六进制表示形式

例如,您可以使用以下命令定义实用程序函数:

然后我们可以实现以下功能:

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

这就给了我们:

Prelude Data.Char Data.Bits> encDec "this is a test" "k"
"1f0302184b02184b0a4b1f0e181f"
请注意,此处不需要使用
长度
,事实上,没有长度更安全,您可以使用
循环

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
中看到的输出(在预期的输出中出现了一个简单的复制粘贴错误)。

您可以对ASCII字符的索引号进行异或运算。然后将结果转换回ascii,而不是十六进制字符串。
chr
返回给定ascii值的字符。它不会将数字转换为十六进制。如果您想要十六进制输出,您需要找到除
chr
@WillemVanOnsem之外的其他内容谢谢!但是现在encDec不是幂零的,对吗?相反,我必须使用一些“chr”。加密文本上的“fromHex”,然后将其全部放入“encDec”中?我这样问是因为我不确定我是否正确理解了逻辑here@arryn:为什么不呢
zipWith
从一个列表用尽时停止。因此,如果
text
耗尽,无论
循环键
是否耗尽(不能耗尽),它都将停止。我的意思是,它不是幂零的,因为“toHex”而不是“chr”。因此,如果我将“encDec”应用于先前加密的文本,则不会得到初始文本,而只会得到更加密的文本one@arryn:啊,是的。为了防止这种情况发生,您应该制作一些“解码”十六进制流的东西,而不是使用
ord
。但是你当然不能再直接使用
“这是一个测试”
来编码数据了。我得到了第二行,我不知道如何转换成第一行line@arryn丹尼尔说的是这两个字符串是相同的。例如,
'\x1f'
'\US'
是同一个字符的两种不同表示形式。@chi那么有没有办法让程序以'\x1f'的方式显示结果?@arryn在打印结果之前,你需要使用上面发布的Willem的
到hex
之类的东西将其转换为正确的十六进制代码。此转换不用于返回结果,只用于以所需的表示形式打印结果。不过,
“\x1f\x03…”
“1f03…”
之间存在差异。实际结果与前者相同,但与后者不同。
encDec :: String -> String -> String
encDec text key = stringXor (cycle key) text
> "\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"