kir*_*rov 2 base64 encoding haskell decoding
我正在尝试测试encode和decode函数(在 中定义Data.ByteString.Base64.Lazy)是相反的:
import qualified Data.ByteString.Lazy as BL
encoded :: Gen BL.ByteString
encoded = do
body <- concat <$> listOf (group 0)
end <- group =<< choose (0, 2)
return . BL.pack $ body <> end
where
group :: Int -> Gen [Word8]
group pad = do
letters <- vectorOf (4 - pad)
. elements . map (fromIntegral . ord)
$ ['A'..'Z'] <> ['a'..'z'] <> ['0'..'9'] <> ['+','/','=']
return $ letters <> replicate pad 61 -- 61 is ascii for =
prop_encDec = forAll encoded $ \b ->
[b] == (encode <$> rights [decode b])
Run Code Online (Sandbox Code Playgroud)
但是 QuickCheck 发现了一个问题:
=== prop_encDec ===
*** Failed! Falsifiable (after 1 test):
"1yx="
Run Code Online (Sandbox Code Playgroud)
我已经调查过这个问题一定与非规范编码有关,但我很难理解它是什么以及如何处理它。你能解释一下这个例子为什么解码“1yx=”和重新编码会产生“1yw=”。
问题是x确实包含与编码无关的位置。
让我详细说明:base64 字符串1yx=将被解码为以下二进制模式
base64: 1 y x =
binary: 000001 110010 110001 000000
Run Code Online (Sandbox Code Playgroud)
然而,=字符串的末尾告诉编码器最后 8 位不相关,所以
000001 110010 110001 000000
^^^^^^ ^^^^^^ ^^^^
Run Code Online (Sandbox Code Playgroud)
只有标记的位将被解码为
binary: 000001 110010 1100
Run Code Online (Sandbox Code Playgroud)
如您所见,01由 编码的最后两位 ( )x被忽略
然后,如果我们对解码后的数据进行编码,编码器将用零位填充位流,从而导致
binary: 000001 110010 110000 000000
^^ ^^^^^^
base64: 1 y w =
Run Code Online (Sandbox Code Playgroud)
所以总结一下:编码器无法“正确”重新编码解码,1yx=因为它包含因解码而丢失的信息。
为了您的测试目的,我建议交换操作顺序。因此,生成一些随机字符串作为输入,对其进行编码,然后对其进行解码并将其与原始输入进行比较。
您可能还想查看Wikipedia 文章中 Base64 编码的示例部分。它包含有关数据填充的商品示例。
关于规范和非规范编码:
当且仅当所有填充位都为零时,base64 字符串是规范的,如果填充位之一不为零,则该字符串是非规范的。因此,如果 base64 字符串末尾有 1 =,则最后 8 位必须为零才能使其成为规范;如果字符串末尾有 2 =,则最后 16 位必须为零。
所以该字符串1yx=是非规范的,因为正如我们在上面看到的,填充位之一是 1。另一方面,该字符串1yw=是规范的,因为所有 8 个填充位都为零。
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |