17

I am writing a C# application to decode this string:

"--W3sic3RhcnRfdGltZSI6IjAiLCJwcm9kdWN0X2lkIjoiODQwMDMzMDQiLCJ1cmwiOiIifSx7InN0YXJ0X3RpbWUiOiI3OSIsInByb2R1Y3RfaWQiOiI4NDAzNjk2MSIsInVybCI6IiJ9LHsic3RhcnRfdGltZSI6IjgyIiwicHJvZHVjdF9pZCI6Ijg0MDAzMDIwIiwidXJsIjoiIn0seyJzdGFydF90aW1lIjoiMTA5IiwicHJvZHVjdF9pZCI6IiIsInVybCI6Imh0dHBzOi8vYmxvZy5sYXJlaW5lZHVzaG9wcGluZy5jYS8yMDE3LzAxL3RyYW5zZm9ybWVyLXNlcy12aWV1eC1nYW50cy1kZS1jdWlyLWVuLTUtbWludXRlcy8ifV0="

It works when I copy/paste it into this online tool: https://www.base64decode.org

But it throws an exception when I use Convert.FromBase64String(str):

System.FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

Why?

mcarton
  • 27,633
  • 5
  • 85
  • 95
Drake
  • 2,679
  • 4
  • 45
  • 88
  • 4
    remove the "--" – Parker Jul 02 '17 at 02:03
  • Why? It's valid Base64 characters – Drake Jul 02 '17 at 02:04
  • 1
    This post may answer your question. https://stackoverflow.com/questions/15114044/the-input-is-not-a-valid-base-64-string-as-it-contains-a-non-base-64-character – FullStackDeveloper Jul 02 '17 at 02:05
  • 2
    @Darius no it's not. That's from a header or something, it's not in the `A-Z0-9` range – Parker Jul 02 '17 at 02:06
  • Maybe there's a `newline` character, which goes into the code! and while pasting I did not find any newline being pasted. – Ayushya Jul 02 '17 at 02:07
  • 1
    They shouldn't be valid. It probably works on base64decode.org because the site is removing them before decoding. You can see that if you add or remove more minus symbols, the output stays the same. – snixtho Jul 02 '17 at 02:08
  • Aren't `-` and `+` valid base64 characters? – Drake Jul 02 '17 at 02:21
  • 1
    + is, - is not https://stackoverflow.com/questions/13195143/range-of-valid-character-for-a-base-64-encoding/13195218 – Parker Jul 02 '17 at 02:24
  • 1
    The accepted answer is not correct. `-` is a valid character in some variants, but not the one uses by .Net. It is also not valid in PHP, which the website uses, but the standard PHP variant ignores invalid characters where the .Net variant does not. Additionally, URL decoding will remove `+` from the encoding string making it invalid. – Alexander Higgins Jul 02 '17 at 02:56

3 Answers3

21

URL Decoding will remove + from a base64 string making it invalid. If you decode 'a+==' the result will be the character 'k'. If you use URL Decoding to decode 'a+==' the URL decoding will turn the string into 'a ==' and you will get an exception trying to decode it.

In short, the .Net Framework is using a variant of Base64 encoding which does not allow invalid characters and PHP, used by the site in question, is using another variant which allows non-valid characters but discards them.

Base64 encoding converts three octets into four encoded characters. Valid characters for the first 62 of the 64 characters in Base64 encoding:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789

There are several variants which allow different characters for characters 62 and 63. With C#, as with the most common variants, the full character set is:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

https://msdn.microsoft.com/en-us/library/dhx0d524(v=vs.110).aspx

The base-64 digits in ascending order from zero are the uppercase characters "A" to "Z", the lowercase characters "a" to "z", the numerals "0" to "9", and the symbols "+" and "/". The valueless character, "=", is used for trailing padding.

This variant is known is the standard 'base64' encoding for RFC 3548 or RFC 4648 in which invalid values are forbidden unless otherwise specified.

PHP uses Base64 transfer encoding for MIME (RFC 2045) which allows non-valid characters but discards them.

In all other Base64 variants non-valid characters are forbidden.

If the original Base64 was actually supposed to contain the - character it is using a different variant.

See: https://en.wikipedia.org/wiki/Base64#Variants_summary_table

miken32
  • 42,008
  • 16
  • 111
  • 154
Alexander Higgins
  • 6,765
  • 1
  • 23
  • 41
  • 2
    Yes, I spend 3 days to found out this reason finally, because I use WebUtility.UrlDecode to wrap the base64 image data. (URL Decoding will remove + from a base64 string making it invalid) is right and must aware if post base64 data. – Cheung Nov 26 '19 at 03:49
6

Your code is not a valid Base64 string. The - characters in the beginning of the string are invalid. You can convert it this way.

using System;
using System.Text;

var decodedString = "--W3sic3RhcnRfdGltZSI6IjAiLCJwcm9kdWN0X2lkIjoiODQwMDMzMDQiLCJ1cmwiOiIifSx7InN0YXJ0X3RpbWUiOiI3OSIsInByb2R1Y3RfaWQiOiI4NDAzNjk2MSIsInVybCI6IiJ9LHsic3RhcnRfdGltZSI6IjgyIiwicHJvZHVjdF9pZCI6Ijg0MDAzMDIwIiwidXJsIjoiIn0seyJzdGFydF90aW1lIjoiMTA5IiwicHJvZHVjdF9pZCI6IiIsInVybCI6Imh0dHBzOi8vYmxvZy5sYXJlaW5lZHVzaG9wcGluZy5jYS8yMDE3LzAxL3RyYW5zZm9ybWVyLXNlcy12aWV1eC1nYW50cy1kZS1jdWlyLWVuLTUtbWludXRlcy8ifV0="
    .Replace("-", "");
var bytes = Convert.FromBase64String(decodedString);
var encodedString = Encoding.UTF8.GetString(bytes);
Console.WriteLine(encodedString);
Saeid
  • 1,573
  • 3
  • 19
  • 37
1

You'll have to remove the -- prefix from your string like was mentioned above. I want to add that I got the same error when I had data:image/jpeg;base64, prefix in my base64 string when using Convert.FromBase64String(str).

Removing data:image/jpeg;base64, from the string worked.

jakobinn
  • 1,832
  • 1
  • 20
  • 20