web service utf8 arabic decoding - c#

I built a c# web service that accepts unicode characters
I have a client that consumes this web service from php to insert data to MS SQL database
It runs correctly with english characters but when he push arabic text it insert "???????" chars to the database
I tried to decode utf8 to unicode with no luck
here is my conversion code:
private byte[] GetRawBytes(string str)
{
int charcount = str.Length;
byte[] byttemp = new byte[charcount];
for (int i = 0; i < charcount; i++)
{
byttemp[i] = (byte)str[i];
}
return byttemp;
}
private string UTF8toUnicode(string str)
{
byte[] bytUTF8;
byte[] bytUnicode;
string strUnicode = String.Empty;
bytUTF8 = GetRawBytes(str);
bytUnicode = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, bytUTF8);
strUnicode = Encoding.Unicode.GetString(bytUnicode);
return strUnicode;
}

Related

C# code php equivalent md5 hash

I have this C# code:
public static string Encript(string strData)
{
string hashValue = HashData(strData);
string hexHashData = ConvertStringToHex(hashValue);
return hexHashData;
}
public static string HashData(string textToBeEncripted)
{
//Convert the string to a byte array
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
//Compute the MD5 hash algorithm
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
return System.Text.Encoding.Unicode.GetString(byteHashValue);
}
public static string ConvertStringToHex(string asciiString)
{
string hex = "";
foreach (char c in asciiString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint) System.Convert.ToUInt32(tmp.ToString()));
}
return hex;
}
Here you can see an online version.As you can see for the string "test" I get the output "5c82e9e41c7599f790ef1d774b7e6bf"
And this is what I tried on php side
$a = "test";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a);
echo $a;
But the value of the php code is "c8059e2ec7419f590e79d7f1b774bfe6".Why is not working?
Edit:Looks like the C# code is incorrect and needs to be replaced
The correct MD5 hash for 'test' is '098f6bcd4621d373cade4e832627b4f6' in PHP.
I tested it with this code in C#
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
It will generate the same hash as PHP will, without the 'convert encoding' method you are using.
I believe converting the encoding is what is giving you a different answer, try it without
$a = mb_convert_encoding($a, "UTF-16LE");
The problem is that you are converting the result incorrectly in your C# code. If you put a breakpoint in the code after you call ComputeHash, and examine the value of byteHashValue, you'll see that it's c8059e2e....
Or, just add this code to your ComputeHash method:
Console.WriteLine(BitConverter.ToString(byteHashValue));
I would suggest rewriting your code to be:
public static string Encript(string strData)
{
string hashValue = HashData(strData);
return hashValue;
}
public static string HashData(string textToBeEncripted)
{
//Convert the string to a byte array
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
//Compute the MD5 hash algorithm
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
return BitConverter.ToString(byteHashValue).Replace("-", "");
}
Oh, and a side note: the word is "Encrypt," not "Encript."
The problem in your case is not the encoding, but your conversion to string on the C# side. As long as you use the same encoding everywhere, it should work as expected. But note, that most of the online hashers use ASCII encoding, whereas you use System.Text.Encoding.Unicode which is UTF-16, thus the results will differ from the online encoders.
The code below will give the same result as your PHP snippet (ie c8059e2ec7419f590e79d7f1b774bfe6)
public static void Main(string[] args)
{
string a = "test";
string en = HashData(a);
Console.WriteLine(en);
}
public static string HashData(string textToBeEncripted)
{
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (var b in byteHashValue)
s.Append(b.ToString("x2"));
return s.ToString();
}
If you use System.Text.Encoding.ASCII instead, you will get 098f6bcd4621d373cade4e832627b4f6 as suggested in other answers. But then you'll have to use ASCII encoding in your PHP code as well.
This is because with UTF16 every character is represented by two bytes, and not only by one. Thus the byteDataToHash will have twice the size ([116, 0, 101, 0, 115, 0, 116, 0] vs [116, 101, 115, 116] in your case). And a different bytevector of course leads to a different hashvalue. But as said above, as long as all included components use the same encoding, it does not really matter which one you use.

generate HMAC-SHA1 in C#

I am trying to make use of a REST API using C#.
The API creator has provided below pseudo code for hmac creation.
var key1 = sha1(body);
var key2 = key1 . SECRET_KEY;
var key3 = sha1(key2);
var signature = base64_encode(key3);
In the above pseudo code , body is html request body string , and SECRET_KEY
is the secret key provided by REST API provider.
As per my knowledge , I need to use System.Security.Cryptography.HMACSHA1 class
to implement this.
But am not able to completely implement above logic in C#.
Any suggestions ?
Direct mapping of above code to C# would be something like:
static string ComputeSignature(byte[] body, byte[] secret) {
using (var sha1 = SHA1.Create())
{
var key1 = sha1.ComputeHash(body);
var key2 = key1.Concat(secret).ToArray();
var key3 = sha1.ComputeHash(key2);
return Convert.ToBase64String(key3);
}
}
If you have request body as a string, convert it to byte array using proper encoding, for example:
var body = Encoding.UTF8.GetBytes(bodyAsString);
If you have your secret as string - that depends on how api developer expects it to be converted to byte array. Most likely it's already HEX or base64-encoded string.
The issue to make it work in c# is that you need to take the hex format into consideration and then in some cases for it to work the final result should be lower case (example if you're using this for a quickblox api or something)
private string GetHashedMessage(String _secret)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(_secret);
String _message= "Your message that needs to be hashed";
HMACSHA1 hmacsha1 = new HMACSHA1(keyByte);
byte[] messageBytes = encoding.GetBytes(_message);
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
return ByteToString(hashmessage).ToLower();
}
public string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
reference: http://billatnapier.com/security01.aspx

Ruby sha and hash to c#

Im trying to translate this to c#
f1 = Digest::SHA1.hexdigest(#password)
f2 = nonce + ":" + f1
Digest::MD5.hexdigest(f2)
My Code
private static string GetSHA1HashData(string data)
{
//create new instance of md5
SHA1 sha1 = SHA1.Create();
//convert the input text to array of bytes
byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data));
//create new instance of StringBuilder to save hashed data
StringBuilder returnValue = new StringBuilder();
//loop for each byte and add it to StringBuilder
for (int i = 0; i < hashData.Length; i++)
{
returnValue.Append(hashData[i].ToString());
}
// return hexadecimal string
return returnValue.ToString();
}
public static string CreateMD5Hash(string input)
{
// Use input string to calculate MD5 hash
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
// To force the hex string to lower-case letters instead of
// upper-case, use he following line instead:
// sb.Append(hashBytes[i].ToString("x2"));
}
return sb.ToString();
}
Call
var nonce = "1386755695841";
var password = "edc123";
var sha = GetSHA1HashData(password);
var md5 = CreateMD5Hash(nonce + ":" + sha);
But i cant get it right, any ideas
The problem is that .NET uses UTF-16 by default whilst Ruby will use something else (normally UTF-8, but it may also respect encoding that has been set by database or web source).
I think you just need to alter one line:
//convert the input text to array of bytes
byte[] hashData = sha1.ComputeHash(Encoding.ASCII.GetBytes(data));
You may need UTF-8 or even some other encoding instead, depending on the range of passwords accepted by the Ruby version. However, the ASCII coding should at least prove correctness of this answer in general from your sample data.

failed to open sqlite database with persian character in the path

I am using a SQLite database for my program. Everything works fine when I am using English characters in the database path . but when I want to open my SQLite database with Persian characters in its path it fails to open . I searched the internet and found two answers for other languages but it did not worked for Persian.
the two option:
First option:
var dbPath2 =
Path.Combine(Windows.Storage.ApplicationData.Current.RoamingFolder.Path,
"test.db");
string utf8String = String.Empty;
// Get UTF16 bytes and convert UTF16 bytes to UTF8 bytes
byte[] utf16Bytes = Encoding.Unicode.GetBytes(dbPath2);
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode,
Encoding.UTF8, utf16Bytes);
// Fill UTF8 bytes inside UTF8 string
for (int i = 0; i < utf8Bytes.Length; i++)
{
// Because char always saves 2 bytes, fill char with 0
byte[] utf8Container = new byte[2] { utf8Bytes[i], 0 };
utf8String += BitConverter.ToChar(utf8Container, 0);
}
string dbPath = utf8String;
var db = new SQLite.SQLiteConnection(dbPath)
Second option (In Sqlite.cs comes when you add the reference)
public SQLiteConnection(string databasePath, bool
storeDateTimeAsTicks = false)
{
DatabasePath = databasePath;
Sqlite3DatabaseHandle handle;
var r = SQLite3.Open16(DatabasePath, out handle);
Handle = handle;
if (r != SQLite3.Result.OK)
{
throw SQLiteException.New(r, String.Format("Could not
open database file: {0} ({1})", DatabasePath, r));
}
_open = true;
StoreDateTimeAsTicks = storeDateTimeAsTicks;
BusyTimeout = TimeSpan.FromSeconds(0.1);
}
thanks

asp.net mvc file download --System.FormatException: An invalid character was found in the mail header

Our website has files in a few different languages - French, Spanish, Portuguese, and English. When a user uploads a file that contains special characters like ó or ç or ã etc i get an error message when i return File(data, "application/octet-stream", name); in MVC i get the exception:
System.FormatException: An invalid character was found in the mail header.
I found an article in MSDN for this showing how to set the mailmessage to UTF-8 encoding to avoid this. But i do not know how to UTF-8 encode the filename when using the MVC file actionresult. I found an article on the net to UTF-8 encode a string but when I try to use it I get a garbage name so I guess I do not understand what UTF-8 encoding is supposed to do to the string. Here is the sample code found in this blog post: An invalid character was found in the mail header
public static string GetCleanedFileName(string s)
{
char[] chars = s.ToCharArray();
var sb = new StringBuilder();
for (int index = 0; index < chars.Length; index++)
{
string encodedString = EncodeChar(chars[index]);
sb.Append(encodedString);
}
return sb.ToString();
}
private static string EncodeChar(char chr)
{
var encoding = new UTF8Encoding();
var sb = new StringBuilder();
byte[] bytes = encoding.GetBytes(chr.ToString());
for (int index = 0; index < bytes.Length; index++)
{
sb.AppendFormat("%{0}", Convert.ToString(bytes[index], 16));
}
return sb.ToString();
}
Maybe try another function encoding from and to utf8
//UTF8
public static string ConvertToUTF8(string inputString)
{
string toReturn = "";
byte[] arr = Encoding.UTF8.GetBytes(inputString);
for (int i = 0; i &lt arr.Length; i++)
{
toReturn += arr[i].ToString() + " ";
}
return toReturn;
}
public static string ConvertFromUTF8(string inputString)
{
inputString = inputString.Trim();
string result = "";
string[] parts = inputString.Split(' ');
byte[] bytes = new byte[parts.Length];
for (int i = 0; i &lt parts.Length; i++)
{
if (parts[i] == "")
{
continue;
}
try
{
bytes[i] = Convert.ToByte(parts[i]);
}
catch (Exception)
{
MessageBox.Show("Input string was not in a correct format.");
}
}
try
{
result = Encoding.UTF8.GetString(bytes);
}
catch (Exception)
{
throw;
}
return result;
}
I think i have got an idea you have to convert your string not to utf-8 but to utf-16
because utf-8 is encripted ascii as i think.
UTF-16 represents every character using two bytes. UTF-8 uses the one byte ASCII character encodings for ASCII characters and represents non-ASCII characters using variable-length encodings. Keep in mind that while UTF-8 can save space for Western languages, which is an argument often used by proponents, it can actually use up to three bytes per character for other languages.
And that symbols you wrote are not ASCII

Categories