3

这是我在 Haskell 中尝试做的事情:

  • 以 ByteString 格式接收消息(懒惰或严格无关紧要)
  • 使用 RSA 公钥加密消息
  • base64 对加密消息进行编码

我正在使用的RSA 库在内部处理惰性字节字符串。但是,Base64库仅使用严格的 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]

不幸的是,有时这会失败。当我解密以这种方式加密的消息时,有时会产生垃圾,然后是实际消息。我不确定问题出在哪里:是从惰性字节字符串转换为严格字节字符串还是 base64 编码步骤?还是两者兼而有之?

惰性字节字符串只是严格字节字符串块的列表。我是否通过转换隐式修改消息的长度?

请赐教。

4

1 回答 1

4

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

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

请注意,即使您删除了=用于填充输出的字符,这些也是不同的。输入的填充仍然会导致问题。

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

或者,如果您不介意将整个内容保存在内存中,请将惰性字节字符串转换为严格字节字符串,一步对整个内容进行编码,然后再转换回来(如有必要)。

于 2012-04-14T15:29:13.123 回答