Passing a url encoded byte array - c#

I need to pass a byte array via a URL. So I am encoding it with the UrlEncode Method like this:
string ergebnis = HttpUtility.UrlEncode(array);
The result is the following string: %00%00%00%00%00%25%b8j
Now when I pass this string in a URL like this http://localhost:51980/api/Insects?Version=%00%00%00%00%00%25%b8j
This is my Get function:
public List<TaxonDiagnosis> Get([FromUri] string version)
{
List<TaxonDiagnosis> result = new List<TaxonDiagnosis>();
result = db.TaxonDiagnosis.ToList();
byte[] array = HttpUtility.UrlDecodeToBytes(version);
if (version != null)
result = db.GetTaxonDiagnosis(array).ToList();
return result;
}
The problem is, version's value isn't %00%00%00%00%00%25%b8j. Instead it is this \0\0\0\0\0%�j. This of course causes problems when I try to decode it into a byte array again.
How can I pass the correct string in the Url?

As suggested by Jon Skeet, I encoded the arraywith a URL-safe base64 decodabet like in this post: How to achieve Base64 URL safe encoding in C#?

Related

Could not decode JWT payload from base64

I'm going to decode a JWT token from request header, it looks like this:
eyJzdWIiOiIxIiwiZXZlbnRfaWQiOiI3ZTA3Y2JmNC0wYjYyLTQ1MzMtYmE5ZC1mZGFjNDkyNTNjZTUiLCJpYXQiOiIxNTkwODk4Mzg1IiwiZXhwIjoiMTU5MDkwMTk4NSIsImlzcyI6ImxvY2FsaG9zdDo0NDM4NyIsInRpbWV6b25lX29mZnNldCI6LTcsInVzciI6Im1pbmcuaGlldS4xMzEyIiwiYWxpYXMiOiJNaW5nIEhpZXUiLCJwaG9uZSI6IjA4NDQ1OTAyNTIiLCJlbWFpbCI6ImhpZXVhbWlAZ21haWwuY29tIn0
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
When passing the token above to decode method, it throws an exception that tells:
Invalid length for a Base-64 char array or string
dotnetfiddle referrence: https://dotnetfiddle.net/Z2TUz9
But when using it in javascript (using atob function), it works properly.
Could anyone tell me why, then tell me how can I decode it in C#?
Before I get into detail about the question, I would generally suggest using a JWT library that can do all that needs to be done with a few function calls.
As a Base64 string, it is indeed too short. A valid Base64 encoded string should have a length that is dividable by 4 and should be padded with 1 or 2 padding characters = if necessary. But JWT uses the slightly different Base64url encoding and in this encoding padding is optional.
But the C# Base64 decoder is quite strict in this regard.
Therefore you need to convert from Base64Url to Base64 and add the missing padding. Besides that, there are also two Base64Url specific characters that need to be converted back to Base64, as shown in the following code:
using System;
public class Program
{
public static void Main()
{
string token = "eyJzdWIiOiIxIiwiZXZlbnRfaWQiOiI3ZTA3Y2JmNC0wYjYyLTQ1MzMtYmE5ZC1mZGFjNDkyNTNjZTUiLCJpYXQiOiIxNTkwODk4Mzg1IiwiZXhwIjoiMTU5MDkwMTk4NSIsImlzcyI6ImxvY2FsaG9zdDo0NDM4NyIsInRpbWV6b25lX29mZnNldCI6LTcsInVzciI6Im1pbmcuaGlldS4xMzEyIiwiYWxpYXMiOiJNaW5nIEhpZXUiLCJwaG9uZSI6IjA4NDQ1OTAyNTIiLCJlbWFpbCI6ImhpZXVhbWlAZ21haWwuY29tIn0";
token = token.Replace('_', '/').Replace('-', '+');
switch (token.Length % 4)
{
case 2: token += "=="; break;
case 3: token += "="; break;
}
var decoded = Convert.FromBase64String(token);
var decodedToken = System.Text.Encoding.Default.GetString(decoded);
Console.WriteLine(decodedToken);
}
}
Code in dotnetfiddle
The datatype of decoded is byte[] and the output would be just the name of the type. To convert it to string and print the JSON I added another line.
The next step from here would be to convert the JSON to a C# object or to use a library as mentioned in the beginning.
You can do it without DRY , this problem can be resolved by
System.IdentityModel.Tokens.Base64UrlEncoder.DecodeBytes(someBase64Url);
or
WebEncoders.Base64UrlDecode(someBase64Url);

"Specified value has invalid Control characters" when converting SHA512 output to string

I am attempting to create an Hash for an API.
my input is something like this:
FBN|Web|3QTC0001|RS1|260214133217|000000131127897656
And my expected output is like :
17361DU87HT56F0O9967E34FDFFDFG7UO334665324308667FDGJKD66F9888766DFKKJJR466634HH6566734JHJH34766734NMBBN463499876554234343432456
I tried the bellow but I keep getting
"Specified value has invalid Control characters. Parameter name: value"
I am actually doing this in a REST service.
public static string GetHash(string text)
{
string hash = "";
SHA512 alg = SHA512.Create();
byte[] result = alg.ComputeHash(Encoding.UTF8.GetBytes(text));
hash = Encoding.UTF8.GetString(result);
return hash;
}
What am I missing?
The problem is Encoding.UTF8.GetString(result) as the data in result is invalid UTF-8 (it's just binary goo!) so trying to convert it to text is invalid - in general, and specifically for this input - which results in the Exception being thrown.
Instead, convert the byte[] to the hex representation of said byte sequence; don't treat it as UTF-8 encoded text.
See the questions How do you convert Byte Array to Hexadecimal String, and vice versa? and How can I convert a hex string to a byte array?, which discuss several different methods of achieving this task.
In order to make this work you need to convert the individual byte elements into a hex representation
var builder = new StringBuilder();
foreach(var b in result) {
builder.AppendFormat("{0:X2}", b);
}
return builder.ToString();
You might want to consider using Base64 encoding (AKA UUEncode):
public static string GetHash(string text)
{
SHA512 alg = SHA512.Create();
byte[] result = alg.ComputeHash(Encoding.UTF8.GetBytes(text));
return Convert.ToBase64String(result);
}
For your example string, the result is
OJgzW5JdC1IMdVfC0dH98J8tIIlbUgkNtZLmOZsjg9H0wRmwd02tT0Bh/uTOw/Zs+sgaImQD3hh0MlzVbqWXZg==
It has an advantage of being more compact than encoding each byte into two characters: three bytes takes four characters with Base64 encoding or six characters the other way.

Decoding a string to get the value "Indsætning"

I have a string (C# code) that looks as follows:
string s = "Indsætning";
It is encoded in some way that I am not sure of.
I'd like to decode it so that I get the following string:
Indsætning
I have tried with
string s1 = HttpUtility.UrlDecode(s);
string s2 = HttpUtility.HtmlDecode(s);
However, I don't get the string that I am looking for.
Any help is appreciated.
Convert the string to bytes and then using the Encoding class to get the UTF-8 string representation.
string s = "Indsætning";
byte[] sBytes = s.Select(x => (byte)x).ToArray();
string decoded = Encoding.UTF8.GetString(sBytes);
Edit - As mentioned in the comments, this assumes that the string being converted is of a particular encoding (Latin-1 in this case). Therefore, it won't necessarily work for all strings, unless you know that they've all been encoded into the same format.

Encoding strings to and from base-64

I'm trying to encode some strings back and forth from base-64 string and I'm having truble to get the right result.
string text = base64string.... //Here I have a base-64 string.
byte[] encodedByte = System.Text.ASCIIEncoding.ASCII.GetBytes(text);
string base64Encoded = Convert.ToBase64String(encodedByte);
if (text == base64Encoded) //If the new encoded string is equal to its original value
return base64Encoded;
I have tried my ways to do this and I don't seem to get the right result. I have tried both with System.Text.Encoding.Unicode and System.Text.Encoding.UTF8
What could be the problem? Does anyone have a proper solution?
string text = base64string.... //Here I have a base-64 string.
byte[] encodedByte = System.Text.ASCIIEncoding.ASCII.GetBytes(text);
string base64Encoded = Convert.ToBase64String(encodedByte);
You are double encoding the string. You begin with a base64 string, get the bytes, and then encode it again. If you want to compare you will need to begin with the original string.
If text is a base-64 string, then you are doing it backwards:
byte[] raw = Convert.FromBase64String(text); // unpack the base-64 to a blob
string s = Encoding.UTF8.GetString(raw); // assume the blob is UTF-8, and
// decode to a string
which will get you it as a string. Note, though, that this scenario is only useful for representing unicode text in an ascii format. Normally you wouldn't base-64 encode it if the original contents are string.
Convert whatever it is that you need in Base64 into a Byte array then use the FromBase64String and ToBase64String to convert to and from Base64:
Byte[] buffer = Convert.FromBase64String(myBase64String1);
myBase64String2 = Convert.ToBase64String(buffer);
myBase64String1 will be equal to myBase64String2. You will need to use other methods to get your data type into a Byte array and the reverse to get your data type back. I have used this to convert the content of a class into a byte array and then to Base64 string and write the string to the filesystem. Later I read it back into a class instance by reversing the process.
You have the encoding code correctly laid out. To confirm whether the base64-encoded string is correct, you can try decoding it and comparing the decoded contents to the original:
var decodedBytes = Convert.FromBase64String(base64encoded);
var compareText = System.Text.Encoding.ASCII.GetString(decodedText);
if (text == compareText)
{
// carry on...
return base64encoded;
}

Invalid length for a Base-64 char array

I'm getting a "Invalid length for a Base-64 char array." inside of the IF(){...} are variations i have tried to get it to work. it fails in the first line without calling decrypt(...) proving it's not that functions problem. i get the same error inside with the first decrypt(...) call. the last one using the encoding.ascii... will get me inside the function, but then it fails inside the function. I'm getting the proper encrypted info from the database to string SSnum. it's value is: 4+mFeTp3tPF
try
{
string SSnum = dr.GetString(dr.GetOrdinal("Social Security"));
if (isEncrypted)
{
byte[] temp = Convert.FromBase64String(SSnum);
//SSnum = decrypt(Convert.FromBase64String(SSnum), Key, IV);
//SSnum = decrypt(Encoding.ASCII.GetBytes(SSnum), Key, IV);
}
txt_Social_Security.Text = SSnum;
}
catch { txt_Social_Security.Text = ""; }
I've been told to use the Convert.FromBase64String() and not the ASCII method...so why is it failing, how can i fix it?
Base64 data length should be multiple of 4 and with padding char '='
You can change your data as valid base64 data.
string dummyData = imgData.Trim().Replace(" ", "+");
if (dummyData.Length % 4 > 0)
dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '=');
byte[] byteArray = Convert.FromBase64String(dummyData);
https://stackoverflow.com/a/9301545/2024022
This will help you , try once.
Thanks
suribabu.
it's value is: 4+mFeTp3tPF
You are receiving this error because that value, 4+mFeTp3tPF, is in fact not valid Base64.
Is it possible you are simply missing the required padding character, as so 4+mFeTp3tPF=?
Are you certain that you have a Base64 string? Base64 is a means of encoding binary data into a string while only using standard 7-bit ASCII characters. It's not a string encoding like ASCII and has some control bytes present. You have a Base64 string if you're using Convert.ToBase64String to obtain the value (which, if you're trying to store binary data as a string, is your best bet)
Judging by your error (and your example data), I'm assuming that you do not have a Base64 string. If you need to store binary data in the database, you can either create a column using a binary type or encode the string into Base64 by using Convert.ToBase64String.
byte[] inputData = ...;
string base64String = Convert.ToBase64String(inputData);
byte[] outputData = Convert.FromBase64String(base64String);
Here, outputData should contain the same data as inputData.
If what you have is just an ASCII-encoded string, then your original practice of using System.Text.Encoding.ASCII.GetBytes() is correct, but you should change this to use a Base64 string if you can.
Are you sure that string 4+mFeTp3tPF is well-formed Base64 string?
I've tried some online services - no one could convert it.
replace
byte[] temp = Convert.FromBase64String(SSnum);
to this
var temp = UTF8Encoding.UTF8.GetBytes(SSnum);

Categories