String Haskell中的XORing字符串
我想写一个用XOR密码加密文本的程序。这就是我现在所拥有的: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 =
-- 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"