首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Convert.FromBase64String的奇怪行为

Convert.FromBase64String的奇怪行为
EN

Stack Overflow用户
提问于 2015-03-26 20:09:41
回答 2查看 627关注 0票数 4

为什么下面的代码

代码语言:javascript
复制
var s =  "2I==";
var b = Convert.FromBase64String(s);
var new_s = Convert.ToBase64String(b);

到头来new_s是2A==

s最初是一个较长的字符串(96个字符),但我无法包含它,因为它是一个秘密密钥。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-26 20:19:02

"2I==“表示数字54、8 (填充x2),按维基百科表示。

换言之,所代表的双边投资条约是:

代码语言:javascript
复制
110110 000100 XXXXXX XXXXXX

(其中X代表“我不在乎,它来自填充”)

但是,由于填充表明这里只有一个字节的信息,第二个字符的最后4位与此无关。与以往一样,我们可以将4段6位信息重新格式化为3段8位信息,此时它变得更加清晰:

代码语言:javascript
复制
11011000 0100XXXX XXXXXXXX

您可以看到,第二个字节必须是填充的,因为它的一些位来自填充字符。因此,只有第一个字符和第二个字符的前两位是相关的-它只对单个字节0b11011000进行解码。

现在,当您编码0b11011000时,您知道您将有两个填充字符,第一个字符必须是'2‘(表示位'110110'),但第二个字符可以是其前两个位表示'00’的任何字符。碰巧Convert.ToBase64String使用'A',它对不相关的部分有0位。

我脑海中的问题是为什么编码器会选择使用“I”而不是“A”。我不认为在Base64中这样做是无效的,但这是一个奇怪的选择。

票数 6
EN

Stack Overflow用户

发布于 2015-03-26 20:42:01

乔恩·斯基特为观察到的行为提供了一个很好的解释。但是,在Base64的大多数定义中,输入字符串将被视为无效。这些标准包括以下案文:

当输入组中可用的输入位数少于24个时,将值为零的比特(在右边)相加,形成一个6位组的整数。

  • RFC 1421:互联网电子邮件的隐私增强
  • RFC 2045:多用途互联网邮件扩展(MIME)
  • RFC 4648:Base16、Base32和Base64数据编码

RFC 4648进一步强调了这一点:

基座64和基32编码中的填充步骤如果实现不当,可以导致编码数据的非显着更改。例如,如果输入仅为基64编码的一个八进制,则使用第一个符号的所有六个比特,但只使用下一个符号的前两个比特。这些垫位必须设置为零通过符合编码器..。如果衬垫位尚未设置为零,解码器可以选择拒绝编码。

我们可以假设您的原始输入由一个具有值216 (0xD8)的字节组成。二进制数:

代码语言:javascript
复制
11011000

这需要分成6位组:

代码语言:javascript
复制
110110 00

而且,根据上面引用的定义,最后一组需要填充零:

代码语言:javascript
复制
110110 000000

根据Base64字母表,110110 (十进制:54)映射到字符2,而000000 (十进制:0)映射到字符A。添加=填充以获得24位组,最终结果将是2A==。这是原始输入的唯一有效编码。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29287892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档