【问题标题】:Base64 Encoded String to byte array C# FailingBase64编码字符串到字节数组C#失败
【发布时间】:2016-10-19 03:33:47
【问题描述】:

我们在表单主体中接收来自外部应用程序的 base64 编码字符串,下面是我们用来将字符串解码为字节数组的代码,但是我们遇到了异常

输入字符串

PHBheW1lbnRSZXNwb25zZT48cmVzcG9uc2VDb2RlPjAwMDA8L3Jlc3BvbnNlQ29kZT48cmVzcG9uc2VDb2RlVGV4dD4wLVN1Y2Nlc3NmdWw8L3Jlc3BvbnNlQ29kZVRleHQ + PHJlc3BvbnNlU3VtbWFyeT5HUkVFTjwvcmVzcG9uc2VTdW1tYXJ5PjxwYXltZW50RXZlbnRJZGVudGlmaWVyPlRYTiAzNjM5PC9wYXltZW50RXZlbnRJZGVudGlmaWVyPjxMaXN0Pjxjb21wb25lbnRJRD5UWE4gMzYzOTwvY29tcG9uZW50SUQ + PGNsaWVudElEPkdPVERJU0UwNjwvY2xpZW50SUQ + PGJhbmtBdXRoQ29kZT5UOjEyMzQ8L2JhbmtBdXRoQ29kZT48YnV5bmV0VHhuSUQ + Mzc1PC9idXluZXRUeG5JRD48L0xpc3Q + PHBheW1lbnRJbnN0cnVtZW50UmVmPjwvcGF5bWVudEluc3RydW1lbnRSZWY + PG1hc2tlZENhcmROdW1iZXI + KioqKioqKioqKioqOTY4NjwvbWFza2VkQ2FyZE51bWJlcj48Y2FyZFR5cGU + TUFTVEVSQ0FSRDwvY2FyZFR5cGU + PGV4cGlyeURhdGU + MDMvMjAxNzwvZXhwaXJ5RGF0ZT48Y3VzdG9tRGF0YT4mbHQ7IVtDREFUQVsmbHQ7P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI_Jmd0Ow0KJmx0O1RoaXN0bGVDdXN0b21EYXRhIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiJmd0Ow0KICAmbHQ7T3JkZXJJZCZndDtCVFBQMzYzOSZsdDsvT3JkZXJJZCZndDsNCiAgJmx0O0Ftb 3VudCZndDsxMjAmbHQ7L0Ftb3VudCZndDsNCiZsdDsvVGhpc3RsZUN1c3RvbURhdGEmZ3Q7XV0mZ3Q7PC9jdXN0b21EYXRhPjwvcGF5bWVudFJlc3BvbnNlPg

异常

输入不是有效的 Base-64 字符串,因为它包含非 base-64 字符、两个以上的填充字符或填充字符中的非法字符。

代码

var inputText = // use the data as shown above
byte[] decodedBytes = Convert.FromBase64String(inputText);

我想知道这有什么问题以及为什么会抛出异常,如果我尝试在线转换器,他们能够返回正确的结果。

【问题讨论】:

  • 输入错误。如果我将它放入online decoder 中,我会在一定程度上获得可读的文本/xml 文本,但随后它会退化为胡言乱语。它可能被浏览器或网络服务器损坏(未正确 http 编码?)
  • 错误是准确的。您的 base64 文本至少包含下划线 (_) 字符,这是无效的。你可以试着相信你得到的错误信息。它们通常提供丰富的信息。将_ 替换为+,它将正确转换。下次,当您收到错误提示您的数据无效时,请检查您的数据。

标签: c# base64 decode


【解决方案1】:

谢谢大家的回复。

在研究了 base64 编码的工作原理后,我得到了这个工作。

下面是我用来修复它的代码。

var input = new StreamReader(Request.InputStream).ReadToEnd();
        var inputText = "PHBheW1lbnRSZXNwb25zZT48cmVzcG9uc2VDb2RlPjAwMDA8L3Jlc3BvbnNlQ29kZT48cmVzcG9uc2VDb2RlVGV4dD4wLVN1Y2Nlc3NmdWw8L3Jlc3BvbnNlQ29kZVRleHQ+PHJlc3BvbnNlU3VtbWFyeT5HUkVFTjwvcmVzcG9uc2VTdW1tYXJ5PjxwYXltZW50RXZlbnRJZGVudGlmaWVyPlRYTiAzNjM5PC9wYXltZW50RXZlbnRJZGVudGlmaWVyPjxMaXN0Pjxjb21wb25lbnRJRD5UWE4gMzYzOTwvY29tcG9uZW50SUQ+PGNsaWVudElEPkdPVERJU0UwNjwvY2xpZW50SUQ+PGJhbmtBdXRoQ29kZT5UOjEyMzQ8L2JhbmtBdXRoQ29kZT48YnV5bmV0VHhuSUQ+Mzc1PC9idXluZXRUeG5JRD48L0xpc3Q+PHBheW1lbnRJbnN0cnVtZW50UmVmPjwvcGF5bWVudEluc3RydW1lbnRSZWY+PG1hc2tlZENhcmROdW1iZXI+KioqKioqKioqKioqOTY4NjwvbWFza2VkQ2FyZE51bWJlcj48Y2FyZFR5cGU+TUFTVEVSQ0FSRDwvY2FyZFR5cGU+PGV4cGlyeURhdGU+MDMvMjAxNzwvZXhwaXJ5RGF0ZT48Y3VzdG9tRGF0YT4mbHQ7IVtDREFUQVsmbHQ7P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI_Jmd0Ow0KJmx0O1RoaXN0bGVDdXN0b21EYXRhIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiJmd0Ow0KICAmbHQ7T3JkZXJJZCZndDtCVFBQMzYzOSZsdDsvT3JkZXJJZCZndDsNCiAgJmx0O0Ftb3VudCZndDsxMjAmbHQ7L0Ftb3VudCZndDsNCiZsdDsvVGhpc3RsZUN1c3RvbURhdGEmZ3Q7XV0mZ3Q7PC9jdXN0b21EYXRhPjwvcGF5bWVudFJlc3BvbnNlPg";
        inputText = ValidateBase64EncodedString(inputText);

        byte[] decodedBytes = Convert.FromBase64String(inputText);

        string xml = Encoding.UTF8.GetString(decodedBytes);

       private static string ValidateBase64EncodedString(string inputText)
        {
            string stringToValidate = inputText;
            stringToValidate = stringToValidate.Replace('-', '+'); // 62nd char of encoding
            stringToValidate = stringToValidate.Replace('_', '/'); // 63rd char of encoding
            switch (stringToValidate.Length % 4) // Pad with trailing '='s
            {
                case 0: break; // No pad chars in this case
                case 2: stringToValidate += "=="; break; // Two pad chars
                case 3: stringToValidate += "="; break; // One pad char
                default:
                    throw new System.Exception(
             "Illegal base64url string!");
            }

            return stringToValidate;
        }

【讨论】:

    【解决方案2】:

    这是因为您的自定义数据无效。 在那个 Base64 编码的字符串中,你有一个原始的 [CDATA],它很可能没有正确编码。

    请注意,如果我使用字符串的前 684 个字符,它会正确转换为:

    <paymentResponse><responseCode>0000</responseCode><responseCodeText>0-Successful</responseCodeText><responseSummary>GREEN</responseSummary><paymentEventIdentifier>TXN 3639</paymentEventIdentifier><List><componentID>TXN 3639</componentID><clientID>GOTDISE06</clientID><bankAuthCode>T:1234</bankAuthCode><buynetTxnID>375</buynetTxnID></List><paymentInstrumentRef></paymentInstrumentRef><maskedCardNumber>************9686</maskedCardNumber><cardType>MASTERCARD</cardType><expiryDate>03/2017</expiryDate><customData>&
    

    但是当我们到达 customData 标记时,一切都崩溃了,我想这包含 CDATA xml 内容,它可能不是 base64 编码的。

    所以要么保留 CDATA 内容,要么在将其添加到最终字符串之前对其进行正确编码,以解决问题

    【讨论】:

    • “我想这个包含 CDATA xml 内容,可能不是 base64 编码的”——你猜错了。即使使用 CDATA 部分,XML 也可以(并且可能最初是)编码得很好。 Base64 不关心内容是什么;这就是它起作用的原因。唯一的问题是there's a typo in the base64.
    • @PeterDuniho 您的评论在其基本假设上是不正确的。他发布的字符串的字母数为 1,118 个字符长,如果字符串的长度不是 4 的倍数,则无法对字符串进行 base64 解码。将 1 + 替换为 _ 不会解决问题。 CDATA 部分搞砸了解码。
    • “你的评论在基本假设上是不正确的”——我什么都没假设。我只是按照我的指示替换了字符,它解码得很好。确实,正式地,base64 数据的字符长度必须是 4 的倍数,但大多数解码器都可以容忍缺少尾随零。不正确的字符长度不会阻止成功解码,除非丢失的字符实际上是在某处被截断的数据中的非零值。
    • 在任何情况下,无论您对长度有何看法,以及您使用的解码器如何,CDATA 部分与该问题有任何关系显然是错误的。 Base64 可以成功编码您想要的任何数据,包括 XML 中的 CDATA 部分。它不关心内容是什么,因为它只是对您的数据的 binary 表示进行编码。
    • 问题是关于 dot net 的,因此其他库对损坏输入的容忍度无关紧要,Convert.FromBase64String() 无法处理无效内容。不是你也不是我知道字符串是如何组合在一起的,因为我们知道有人手动输入了它。基本上我们都说同样的话。输入不正确,我只是在“customData”标签内容中查明了失败。似乎不再找到询问者,所以它是否有效,仍然未知。
    猜你喜欢
    • 1970-01-01
    • 2017-01-05
    • 2017-07-22
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多