Reputation: 6258
Is there any combination of a byte[]
that will cause this to fail, other than byteArray being null?
var myString = Convert.ToBase64String(byteArray);
I'm thinking something like... starting or ending with byte zero (null?). An Empty byte[]
? A very large byte[]
? Some sequence of bytes that wouldn't make sense in Base64? My issue is the unknown unknowns.
Upvotes: 3
Views: 2776
Reputation: 1724
Is there any combination of a byte[] that will cause this to fail, other than byteArray being null?
As stated on the docs: no. Exception
-wise the Convert.ToBase64String
overload you are using only throws ArgumentNullException
(when its parameter inArray
is null).
Upvotes: 2
Reputation: 40200
Is there any combination of a byte[] that will cause this to fail
byte[] byteArray = null;
var myString = Convert.ToBase64String(byteArray);
// NullArgumentException.
other than byteArray being null?
Nope.
starting or ending with byte zero (null?)
Ending in 0:
var byteArray = new byte[] {255, 255, 0};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // +voA
Leading 0:
var byteArray = new byte[] {0, 250, 250};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // APr6
By the way...
var byteArray = new byte[] {250, 250};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // +vo=
No, it is not just ignoring the 0.
An Empty byte[]?
var byteArray = new byte[] {};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString.Length); // 0
Empty string.
A very large byte[]?
Ern...
var byteArray = new byte[int.MaxValue]; // OutOfMemoryException
Hmm...
var byteArray = new byte[int.MaxValue / 8];
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString.Length); // 357913940
It survived.
Some sequence of bytes that wouldn't make sense in Base64?
No such thing exists. You take the the input as binary (base 2), do base conversion to base 64, and follow the standard for representation.
My issue is the unknown unknowns.
In general, stick to the documentation and do no try to do something that is not documented.
I suppose there is a chance that there could be a bug in the platform. There are some bugs, none in ToBase64String
that I know of. However - in general - it is not your responsability to fix them or work around them (sometimes you will have to). If you happen to stumble upon one, report it.
The thing with bugs is that they are unknown unknowns until discovered. You can try to have a look here and here. Beyond that, how will I be able to point you to them if I do not know them?
Oh, you want to find bugs? Alright, test (as I did for this answer), and review the source (reference source, .NET Core). Hey, they are using ReadOnlySpan
, I guess that is why it did not blow up with the large array.
Upvotes: 4
Reputation: 650
Anything that can be represented as binary can be base64 encoded. This is because the algorithm deals with the binary representation of data, rather than whatever presentation you are using it as. For this reason any binary string can be encoded, however when you decode you have to be exact about the result type.
It would be a worthwhile exercise, or kata if you would, to create your own base64 encoder and decoder. I've included in my answer my own base64 encoding class to use as a reference. It is far from the most efficient way of doing this, and is probably considerably slower than .NET's native implementation, and it only decodes back into strings. But I think mine is probably easier to read from a beginner's point of view.
public class Base64Utility
{
List<char> characterMap = new List<char>()
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'+', '/'
};
public string Base64Encode(string source)
{
string result = string.Empty;
int octetsMissing = 0;
string byteString = string.Empty;
byte[] bytes = new byte[source.Length];
int[] base10Integers = new int[source.Length];
for (int i = 0; i < source.Length; i++)
{
byte b = Convert.ToByte(source[i]);
bytes[i] = (b);
base10Integers[i] = Convert.ToInt32(bytes[i].ToString(), 10);
byteString += Convert.ToString(bytes[i], 2).PadLeft(8, '0');
}
for (int byteIndex = 0; byteIndex < byteString.Length;)
{
int span = byteString.Length - byteIndex >= 6
? 6
: byteString.Length - byteIndex;
string subString = byteString.Substring(byteIndex, span);
if (subString.Length < 6)
{
octetsMissing = (6 - subString.Length) / 2;
for (int i = subString.Length; i < 6; i++)
{
subString += '0';
}
}
int index = Convert.ToInt32(subString, 2);
result += characterMap[index];
byteIndex += span;
}
for (int i = 0; i < octetsMissing; i++)
{
result += '=';
}
return result;
}
public string Base64Decode(string source)
{
string result = string.Empty;
int[] mappedSource = new int[source.Length];
string[] mappedSourceAsBinary = new string[source.Length];
for (int i = 0; i < source.Length; i++)
{
if(source[i] != '=')
{
mappedSource[i] = characterMap.IndexOf(source[i]);
mappedSourceAsBinary[i] = Convert.ToString(mappedSource[i], 2);
}
if(mappedSourceAsBinary[i] != null)
{
if(mappedSourceAsBinary[i].Length < 6)
{
for(int j = mappedSourceAsBinary[i].Length; j < 6; j++)
{
mappedSourceAsBinary[i] = '0' + mappedSourceAsBinary[i];
}
}
}
}
string temp = string.Empty;
for(int i = 0; i < mappedSourceAsBinary.Length; i++)
{
temp += mappedSourceAsBinary[i];
}
string[] t = new string[temp.Length / 8];
for (int i = 0; i < t.Length; i++)
{
t[i] = temp.Substring(8*i, 8);
int res = Convert.ToInt32(t[i], 2);
char resAscii = Encoding.ASCII.GetString(new byte[] { (byte)res })[0];
result += resAscii;
}
return result;
}
}
}
Upvotes: 1