i have a method that i need to remake in C# based on this python code.
def _generateHash(self, password, time_stamp, nonce):
import hashlib
shaPw = hashlib.sha1()
shaPw.update( password )
m = hashlib.sha1()
m.update(str(time_stamp))
m.update(nonce)
m.update(shaPw.hexdigest())
m.update(self.api_key_secret)
return m.hexdigest()
hashing in C# is allot different compared to python. also my hashing experience is not that great. is there anybody that can help me?
this is wat i have right now.
private string GenerateHash(string password, double timeStamp, string nonce)
{
using (SHA1Managed sha1 = new SHA1Managed())
{
var pwHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(password));
using (SHA1Managed sha1total = new SHA1Managed())
{
sha1total.ComputeHash(Encoding.UTF8.GetBytes(timeStamp.ToString()));
sha1total.ComputeHash(Encoding.UTF8.GetBytes(nonce));
string hexaHashPW = "";
foreach (byte b in pwHash)
{
hexaHashPW += String.Format("{0:x2}", b);
}
sha1total.ComputeHash(Encoding.UTF8.GetBytes(hexaHashPW));
sha1total.ComputeHash(Encoding.UTF8.GetBytes(_SecretApiKey));
var hmac = new HMACSHA1();
//string hexaHashTotal = "";
//foreach (byte b in sha1total.Hash)
//{
// hexaHashTotal += String.Format("{0:x2}", b);
//}
hmac.ComputeHash(sha1total.Hash);
var hexaHashTotal = hmac.Hash;
var endhash = BitConverter.ToString(hexaHashTotal).Replace("-", "");
return endhash;
}
}
}
after even more research and trail and error i found the way to produce the same hash as the python code.
this is the answer for others that have problems with this.
private string GenerateHash(string password, double timeStamp, string nonce)
{
using (SHA1Managed sha1 = new SHA1Managed())
{
var pwHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(password));
using (SHA1Managed sha1total = new SHA1Managed())
{
string hexaHashPW = "";
foreach (byte b in pwHash)
{
hexaHashPW += String.Format("{0:x2}", b);
}
var hmacPW = new HMACSHA1();
hmacPW.ComputeHash(pwHash);
sha1total.ComputeHash(Encoding.UTF8.GetBytes(timeStamp.ToString() + nonce + hexaHashPW + _SecretApiKey));
var hmac = new HMACSHA1();
string hexaHashTotal = "";
foreach (byte b in sha1total.Hash)
{
hexaHashTotal += String.Format("{0:x2}", b);
}
hmac.ComputeHash(sha1total.Hash);
return hexaHashTotal.ToLower();
}
}
}
Related
I have to rewrite this php code to c#
$sign_params = ['name'=>"John", 'age'=>18];
$client_secret = 'test secret key';
ksort($sign_params); // Sort array by keys
$sign_params_query = http_build_query($sign_params); // Forming string like "param_name1=value¶m_name2=value"
$sign = rtrim(strtr(base64_encode(hash_hmac('sha256', $sign_params_query, $client_secret, true)), '+/', '-_'), '='); // get hash code
return $sign;
Here what I try:
public class apiHelper : MonoBehaviour
{
const string client_secret = "test secret key";
public static string checkSign(Dictionary<string, dynamic> fields)
{
//* sort by keys
var list = fields.Keys.ToList();
list.Sort();
string sign_params_query = "";
//* forming string like "param_name1=value¶m_name2=value"
foreach (var key in list)
{
sign_params_query = sign_params_query + key + "=" + fields[key];
if (key != list.Last()) sign_params_query = sign_params_query + "&";
}
//* get hash code
string sign = System.Convert.ToBase64String(GetHash(sign_params_query, client_secret));
char[] charsToTrim = { '=' };
return sign.Replace("+", "-").TrimEnd(charsToTrim);
}
static byte[] GetHash(string url, string key)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key)))
{
byte[] data = hmac.ComputeHash(Encoding.UTF8.GetBytes(url));
return data;
}
}
}
Well, finally I get different hash than in php example ._. What did I wrong? Its my 1st time with cryptho or smth like that
Well, problem wath with strings which have special chars. I have to use url_encode c# equivalent to solve it.
hi i m creating PayUMoney Payment Gateway and i m sending parametrs to c# code..then test site is open..after entring test card no,CVV,test Name my transaction process start but after that my transaction is failed..i dont know how it is?? please help me to solve my problem.
enter code here
public string Generatehash512(string text) //this is Hash generate method
{
byte[] message = Encoding.UTF8.GetBytes(text);
UnicodeEncoding UE = new UnicodeEncoding();
byte[] hashValue;
SHA512Managed hashString = new SHA512Managed();
string hex = "";
hashValue = hashString.ComputeHash(message);
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
return hex;
}
if (!string.IsNullOrEmpty(hash1)) //all parameter that i sent.
{
hash.Value = hash1;
txnid.Value = txnid1;
System.Collections.Hashtable data = new
System.Collections.Hashtable(); // adding values in gash table for data post
data.Add("hash", hash.Value);
data.Add("key", key.Value);
data.Add("txnid", txnid.Value);
string AmountForm =
Convert.ToDecimal(amount.Text.Trim()).ToString("g29");// eliminating trailing zeros
amount.Text = AmountForm;
data.Add("amount", amount.Text.Trim());
data.Add("firstname", firstname.Text.Trim());
data.Add("email", email.Text.Trim());
data.Add("phone", phone.Text.Trim());
data.Add("productinfo", productinfo.Text.Trim());
data.Add("surl", surl.Text.Trim());
data.Add("furl", furl.Text.Trim());
data.Add("lastname", lastname.Text.Trim());
data.Add("curl", curl.Text.Trim());
data.Add("address1", address1.Text.Trim());
data.Add("address2", address2.Text.Trim());
data.Add("city", city.Text.Trim());
data.Add("state", state.Text.Trim());
data.Add("country", country.Text.Trim());
data.Add("zipcode", zipcode.Text.Trim());
data.Add("udf1", udf1.Text.Trim());
data.Add("udf2", udf2.Text.Trim());
data.Add("udf3", udf3.Text.Trim());
data.Add("udf4", udf4.Text.Trim());
data.Add("udf5", udf5.Text.Trim());
data.Add("pg", pg.Text.Trim());
data.Add("service_provider", service_provider.Text.Trim());
data.Add("abc", hash_string);
string strForm = PreparePOSTForm(action1, data);
Page.Controls.Add(new LiteralControl(strForm));
}
in c#
public static string HashToString(string message, byte[] key)
{
byte[] b=new HMACSHA512(key).ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToBase64String(b);
}
client.DefaultRequestHeaders.Add("X-Hash", hash);
var encryptedContent = DataMotion.Security.Encrypt(key, Convert.FromBase64String(iv), serializedModel);
var request = client.PostAsync(ApiUrlTextBox.Text,encryptedContent,new JsonMediaTypeFormatter());
in java:
protected String hashToString(String serializedModel, byte[] key) {
String result = null;
Mac sha512_HMAC;
try {
sha512_HMAC = Mac.getInstance("HmacSHA512");
SecretKeySpec secretkey = new SecretKeySpec(key, "HmacSHA512");
sha512_HMAC.init(secretkey);
byte[] mac_data = sha512_HMAC.doFinal(serializedModel.getBytes("UTF-8"));
result = Base64.encodeBase64String(mac_data);
}catch(Exception e){
}
}
o/p: ye+AZPqaKrU14pui4U5gBCiAbegNvLVjzVdGK3rwG9QVzqKfIgyWBDTncORkNND3DA8jPba5xmC7B5OUwZEKlQ==
i have written hashtostring method in java based on c# code. is this currect? (output is different because every time process is dynamic in both cases.)
With different C# encoding
public static string SHA512_ComputeHash(string text, string secretKey)
{
var hash = new StringBuilder(); ;
byte[] secretkeyBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] inputBytes = Encoding.UTF8.GetBytes(text);
using (var hmac = new HMACSHA512(secretkeyBytes))
{
byte[] hashValue = hmac.ComputeHash(inputBytes);
foreach (var theByte in hashValue)
{
hash.Append(theByte.ToString("x2"));
}
}
return hash.ToString();
}
Both java and C# code are giving same result(same hash code). You should check again.
Replace following line in java code at end
result = Base64.getEncoder().encodeToString(mac_data);
In c#
public static string HMACSHA512(this string Key, string TextToHash)
{
string HmacHashed = "";
if (string.IsNullOrEmpty(Key))
throw new ArgumentNullException("HMACSHA512: Key", "Parameter cannot be empty.");
if (string.IsNullOrEmpty(TextToHash))
throw new ArgumentNullException("HMACSHA512: TextToHash", "Parameter cannot be empty.");
if (Key.Length % 2 != 0 || Key.Trim().Length < 2)
{
throw new ArgumentNullException("HMACSHA512: Key", "Parameter cannot be odd or less than 2 characters.");
}
try
{
using (var HMACSHA512 = new HMACSHA512(Encoding.ASCII.GetBytes(Key)))
{
HmacHashed = BitConverter.ToString(HMACSHA512.ComputeHash(Encoding.ASCII.GetBytes(TextToHash))).Replace("-", string.Empty);
}
return HmacHashed;
}
catch (Exception ex)
{
throw new Exception("HMACSHA512: " + ex.Message);
}
}
When Facebook sends real-time updates, they include a X-Hub-Signature in the HTTP header. According to their documentation (http://developers.facebook.com/docs/api/realtime), they're using SHA1 and the application secret as the key. I tried to verify the signature like this:
public void MyAction() {
string signature = request.Headers["X-Hub-Signature"];
request.InputStream.Position = 0;
StreamReader reader = new StreamReader(request.InputStream);
string json = reader.ReadToEnd();
var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
var hmacBase64 = ToUrlBase64String(hmac);
bool isValid = signature.Split('=')[1] == hmacBase64;
}
private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
hmacAlgorithm.ComputeHash(dataToSign);
return hmacAlgorithm.Hash;
}
}
private static string ToUrlBase64String(byte[] Input) {
return Convert.ToBase64String(Input).Replace("=", String.Empty)
.Replace('+', '-')
.Replace('/', '_');
}
But I can't seem to get this to ever validate. Any thoughts on what I'm doing wrong?
Thanks in advance.
In case someone will need this information:
What Kelvin offered might work, but it seems very cumbersome.
All you need is instead of using the ToUrlBase64String function just use the ConvertToHexadecimal function.
See fully updated code below:
public void MyAction() {
string signature = request.Headers["X-Hub-Signature"];
request.InputStream.Position = 0;
StreamReader reader = new StreamReader(request.InputStream);
string json = reader.ReadToEnd();
var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
var hmacHex = ConvertToHexadecimal(hmac);
bool isValid = signature.Split('=')[1] == hmacHex ;
}
private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
return hmacAlgorithm.ComputeHash(dataToSign);
}
}
private static string ConvertToHexadecimal(IEnumerable<byte> bytes)
{
var builder = new StringBuilder();
foreach (var b in bytes)
{
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
The code below will resolve the problem for you:
public String hmacSha1(String keyString, byte[] in) throws GeneralSecurityException {
Mac hmac = Mac.getInstance("HmacSHA1");
int keySize = keyString.length();
byte[] keyBytes = new byte[keySize];
for (int i = 0; i < keyString.length(); i++) {
keyBytes[i] = (byte) keyString.charAt(i);
}
Key key = new SecretKeySpec(keyBytes, "HmacSHA1");
hmac.init(key);
hmac.update(in);
byte[] bb = hmac.doFinal();
StringBuilder v = new StringBuilder();
for (int i = 0; i < bb.length; i++) {
int ch = bb[i];
int d1 = (ch >> 4) & 0xf;
int d2 = (ch) & 0xf;
if (d1 < 10) {
v.append((char) ('0' + d1));
} else {
v.append((char) ('a' + d1 - 10));
}
if (d2 < 10) {
v.append((char) ('0' + d2));
} else {
v.append((char) ('a' + d2 - 10));
}
}
return v.toString();
}
public String callback(HttpServletRequest request) throws IOException {
InputStream in = request.getInputStream();
StringBuilder builder = new StringBuilder();
byte[] buffer = new byte[1024];
while (in.read(buffer) > 0) {
builder.append(new String(buffer));
}
String signature = request.getHeader("X-Hub-Signature");
try {
String signed = subscriptionService.hmacSha1("YOUR_SECRET", builder.toString().getBytes());
if (signature.startsWith("sha1=") && signature.substring(4).equals(signed)) {
// process the update
....
}
} catch (GeneralSecurityException ex) {
log.warn(ex.getMessage());
}
return null;
}
I'm trying to convert this PHP cookie parsing snippet into C#, but my PHP is a bit rusty. It's taken from a facebook SDK sample.
<?php
define('FACEBOOK_APP_ID', 'your application id');
define('FACEBOOK_SECRET', 'your application secret');
function get_facebook_cookie($app_id, $application_secret) {
$args = array();
parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);
ksort($args);
$payload = '';
foreach ($args as $key => $value) {
if ($key != 'sig') {
$payload .= $key . '=' . $value;
}
}
if (md5($payload . $application_secret) != $args['sig']) {
return null;
}
return $args;
}
$cookie = get_facebook_cookie(FACEBOOK_APP_ID, FACEBOOK_SECRET);
echo 'The ID of the current user is ' . $cookie['uid'];
?>
This is what I have so far, but its not quite right:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
HttpCookie cookie = GetCookie();
IsLoggedIn = cookie != null;
}
private HttpCookie GetCookie()
{
// based on the php example at http://developers.facebook.com/docs/authentication/
HttpCookie cookie = Request.Cookies["fbs_" + FacebookClientId];
StringBuilder payload = new StringBuilder();
if (cookie != null)
{
foreach (string key in cookie.Values.Keys)
{
if (key != "sig")
{
payload.Append(key + "=" + cookie.Values[key]);
}
}
string sig = cookie.Values["sig"];
if (sig == GetMD5Hash(payload.ToString()))
{
return cookie;
}
}
return null;
}
public string GetMD5Hash(string input)
{
MD5CryptoServiceProvider cryptoServiceProvider = new MD5CryptoServiceProvider();
byte[] bytes = Encoding.UTF8.GetBytes(input);
bytes = cryptoServiceProvider.ComputeHash(bytes);
StringBuilder s = new StringBuilder();
foreach (byte b in bytes)
{
s.Append(b.ToString("x2").ToLower());
}
return s.ToString();
}
The one part I'm not sure about is parse_str(trim($_COOKIE['fbs_' . $app_id], '\\"'), $args);. From what I can tell its creating an array out of the trimmed cookie value. Can anyone provide some assistance?
If I'm reading it correctly:
trim($_COOKIE['fbs_' . $app_id], '\\"')
Will trim \ and " from the beginning and end of the value stored in the cookie named fbs_FACEBOOK_APP_ID (The double back-slashes escape the back-slash in a single quoted string. And trim can be told what characters to trim from the string.)
Meanwhile, parse_str then parses that as if it were a query string, into an associative array. So, I'd assume that the value of that cookie should look like a query string.
Hope this helps.
There were a few issues in my original C# version.
I forgot to include the FacebookSecret as salt in the MD5 hash.
The cookie.Value needs to be trimmed and parsed as a query string as George Marian and Alex JL explained.
The parsed cookie values need to be UrlDecoded. I guess ASP.NET UrlEncodes them when creating the Cookie object.
The default encoding should be used to create the hash, not UTF8.
Here's the working solution:
private HttpCookie GetCookie()
{
// based on the php example at http://developers.facebook.com/docs/guides/canvas/#canvas
HttpCookie cookie = Request.Cookies["fbs_" + FacebookClientId];
if (cookie != null)
{
var pairs = from pair in cookie.Value.Trim('"', '\\').Split('&')
let indexOfEquals = pair.IndexOf('=')
orderby pair
select new
{
Key = pair.Substring(0, indexOfEquals).Trim(),
Value = pair.Substring(indexOfEquals + 1).Trim()
};
IDictionary<string, string> cookieValues =
pairs.ToDictionary(pair => pair.Key, pair => Server.UrlDecode(pair.Value));
StringBuilder payload = new StringBuilder();
foreach (KeyValuePair<string, string> pair in cookieValues)
{
Response.Write(pair.Key + ": " + pair.Value + "<br/>\n");
if (pair.Key != "sig")
{
payload.Append(pair.Key + "=" + pair.Value);
}
}
string sig = cookieValues["sig"];
string hash = GetMd5Hash(payload + FacebookSecret);
if (sig == hash)
{
return cookie;
}
}
return null;
}
private static string GetMd5Hash(string input)
{
MD5CryptoServiceProvider cryptoServiceProvider = new MD5CryptoServiceProvider();
byte[] bytes = Encoding.Default.GetBytes(input);
byte[] hash = cryptoServiceProvider.ComputeHash(bytes);
StringBuilder s = new StringBuilder();
foreach (byte b in hash)
{
s.Append(b.ToString("x2"));
}
return s.ToString();
}