这是我要在Haskell中尝试做的事情:
接收ByteString格式的消息(懒惰或严格并不重要)
使用RSA公钥加密消息
base64编码加密的消息
我正在使用的RSA library在内部处理惰性ByteString。但是,Base64库仅使用严格的ByteStrings。我的应用程序使用惰性ByteStrings将消息发送到网络套接字。
因此,看起来我必须在惰性和严格ByteString之间进行转换。
这是我的工作:
encrypt :: CryptoRandomGen t => t -> RSA.PublicKey -> L.ByteString -> L.ByteString
encrypt gen pubkey msg = do
let (ciphertext,_) = RSA.encrypt gen pubkey msg
(L.fromChunks . map encode . L.toChunks) $ ciphertext
decrypt :: RSA.PrivateKey -> L.ByteString -> Either String L.ByteString
decrypt privkey ciphertext = do
dec <- decode $ S.concat $ L.toChunks ciphertext
return $ RSA.decrypt privkey $ L.fromChunks [dec]
不幸的是,有时这失败了。当我解密以这种方式加密的消息时,有时会导致产生垃圾,之后是实际的消息。我不确定问题出在哪里:是从惰性到严格ByteStrings的转换,还是base64编码步骤?还是两者?
惰性ByteString只是严格的ByteString块的列表。是否通过转换来隐式修改消息的长度?
请赐教。
最佳答案
问题在于base64编码将输入的每三个字节(3×8位)映射到输出的四个字节(4×6位),因此,当输入的大小不是三的倍数时,必须添加填充。这意味着将每个块分别编码的结果串联起来可能不会得到与对整个事物进行编码相同的结果。
> encode "Haskell"
"SGFza2VsbA=="
> encode "Hask" `append` encode "ell"
"SGFzaw==ZWxs"
请注意,即使您删除了用于填充输出的
=
字符,它们也有所不同。输入的填充仍然会引起问题。最好的选择也许是找到一个支持惰性字节串的库,但是确保所有块(最后一个块除外)的大小都是三个的倍数,可以作为一种解决方法。
另外,如果您不介意将整个内容保留在内存中,请将惰性字节串转换为严格的字节串,一步编码整个内容,然后再转换回(如有必要)。
关于haskell - 将base64-bytestring与惰性ByteStrings一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10154503/