使用带有惰性ByteStrings的base64-bytestring

时间:2012-04-14 14:51:12

标签: haskell encryption base64 lazy-evaluation bytestring

以下是我在Haskell中要做的事情:

  • 以ByteString格式发送消息(如果懒惰或严格则无关紧要)
  • 使用RSA公钥加密邮件
  • base64编码加密邮件

我正在使用的RSA library在内部处理懒惰的ByteStrings。但是,Base64库仅使用严格的ByteStrings。我的应用程序使用惰性ByteStrings将消息发送到网络套接字。

所以,看起来我必须在lazy和strict ByteStrings之间进行转换。 这是我的所作所为:

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]

不幸的是,有时这会失败。当我解密以这种方式加密的消息时,它有时会导致垃圾后跟实际消息。我不确定问题的确切位置:是从lazy转换为严格的ByteStrings还是base64编码步骤?或者两者兼而有之?

Lazy ByteStrings只是严格的ByteString块的列表。我是否通过转换来隐式修改消息的长度?

请赐教。

1 个答案:

答案 0 :(得分:4)

问题是base64编码将输入的每三个字节(3×8位)映射到四个字节(4×6位)的输出,所以当输入的大小不是三的倍数时,它必须添加填充。这意味着连接分别编码每个块的结果可能不会产生与编码整个事物相同的结果。

> encode "Haskell"
"SGFza2VsbA=="
> encode "Hask" `append` encode "ell"
"SGFzaw==ZWxs"

请注意,即使您删除用于填充输出的=字符,它们也会有所不同。 输入的填充仍然会导致问题。

您最好的选择可能是找到一个支持延迟字节串的库,但确保所有块(最后一个除外)的大小是三的倍数可以作为一种解决方法。

或者,如果您不介意将整个内容保留在内存中,请将lazy bytestring转换为严格的字符串,一步编码整个内容,然后转换回(如有必要)。