3

两种编码可以映射到相同的解码是预期的行为吗?我正在尝试通过对 base64 编码的中间字符串进行完整性检查来解决数字签名问题。

例如,以下 base64 编码:

R0VUDQoNCg0KRnJpLCAwNCBTZXAgMjAwOSAxMTowNTo0OSBHTVQrMDA6MDANCi8=

和:

R0VUCgoKRnJpLCAwNCBTZXAgMjAwOSAxMDozMzoyOCBHTVQrMDA6MDAKLw==

都解码为:

GET


Fri, 04 Sep 2009 11:05:49 GMT+00:00
/

(字符转义后,这是GET\n\n\n Fri, 04 Sep 2009 11:05:49 GMT+00:00\n/:)

第一个编码来自测试两个在线 base64 编码器。

第二种编码来自一个可用的 Objective-C base64 编码

我用 Obj-C 编码器生成的结果有问题吗?

4

5 回答 5

14

另一个证明字符串不相等的例子,使用 Python:

>>> from base64 import decodestring as d
>>> a = "R0VUDQoNCg0KRnJpLCAwNCBTZXAgMjAwOSAxMTowNTo0OSBHTVQrMDA6MDANCi8="
>>> b = "R0VUCgoKRnJpLCAwNCBTZXAgMjAwOSAxMDozMzoyOCBHTVQrMDA6MDAKLw=="
>>> d(a)
'GET\r\n\r\n\r\nFri, 04 Sep 2009 11:05:49 GMT+00:00\r\n/'
>>> d(b)
'GET\n\n\nFri, 04 Sep 2009 10:33:28 GMT+00:00\n/'
>>> d(a) == d(b)
False

较长的字符串使用 CRLF 换行符,较短的字符串使用普通 LF。

于 2009-09-04T11:25:16.267 回答
8

很明显,编码后的字符串在对应于字母数字字符的地方具有相似的模式,而在它们对应于换行符的地方则不同。所以不同之处在于,在“编码”->“解码”方式的某个地方,软件处理换行符(CR (\r)、LF(\n) 或 CRLF(\r\n))的方式不同,这就是为什么你有这样的结果。

除此之外,没有两种不同的方法可以将给定的字符串编码为 Base64,也没有两种不同的方法可以解码有效的 Base64 编码数据。

于 2009-09-04T11:18:14.580 回答
4

实际上,它们不会解码为相同的东西。

$ echo 'R0VUCgoKRnJpLCAwNCBTZXAgMjAwOSAxMDozMzoyOCBHTVQrMDA6MDAKLw==' | base64 -d | hexdump 
0000000 4547 0a54 0a0a 7246 2c69 3020 2034 6553
0000010 2070 3032 3930 3120 3a30 3333 323a 2038
0000020 4d47 2b54 3030 303a 0a30 002f          
000002b
$ echo 'R0VUDQoNCg0KRnJpLCAwNCBTZXAgMjAwOSAxMTowNTo0OSBHTVQrMDA6MDANCi8=' | base64 -d | hexdump
0000000 4547 0d54 0d0a 0d0a 460a 6972 202c 3430
0000010 5320 7065 3220 3030 2039 3131 303a 3a35
0000020 3934 4720 544d 302b 3a30 3030 0a0d 002f
000002f
于 2009-09-04T11:23:03.620 回答
3

正如@sharptooth 所建议的,换行符\r\n在第一个,\n第二个。

>>> base64.b64decode("R0VUDQoNCg0KRnJpLCAwNCBTZXAgMjAwOSAxMTowNTo0OSBHTVQrMDA6MDANCi8=")
'GET\r\n\r\n\r\nFri, 04 Sep 2009 11:05:49 GMT+00:00\r\n/'
>>> base64.b64decode("R0VUCgoKRnJpLCAwNCBTZXAgMjAwOSAxMDozMzoyOCBHTVQrMDA6MDAKLw==")
'GET\n\n\nFri, 04 Sep 2009 10:33:28 GMT+00:00\n/'
于 2009-09-04T11:24:55.300 回答
2

关键是 base 64 字符串解码为字节序列,而不是字符。比较每个 base 64 字符串生成的字节数组表明,不同之处在于行终止的完成方式 - 第一个有 13 后跟 10,第二个只有 10。这是标准的 Windows-vs- Unix 行终止差异。

于 2009-09-04T11:23:39.640 回答