The value that I'm trying to append to is a string. I've been able to convert the string to a byte array using Encoding.ASCII.GetBytes(value) and passing that to the IMemcachedClient:
Appending to Memcached (seems fine)
var value = "Some string value that should get appended";
var bytes = Encoding.ASCII.GetBytes(value);
_memcachedClient.Append(key, new ArraySegment<byte>(bytes, 0, bytes.Length));
Getting appended value from Memcached
var valueAsBase64 = _memcachedClient.Get(key) as string;
var bytes = System.Convert.FromBase64String(valueAsBase64);
var result = Encoding.ASCII.GetString(bytes);
I see the value returned, and it's a string. I'm just not sure how to get the value returned back to the string I started off with (now appended).
The issue I was running into was that I simply was initializing the entry with an empty string instead of an empty byte array. So the return type was a mangled mismash.
The issue came down to the .Append() method not setting an initial value if the key doesn't exist. I'll look a little more into it to see if there's a way of having it do an initial Put if the key doesn't exist.
This works though:
var bytes = (byte[])_cache.Get(key);
var value = Encoding.ASCII.GetString(bytes);
Related
I am running this code:
var timeStamp = DateTime.UtcNow;
var sharedSecret = "xx";
var saltedString = timeStamp.ToString("2021-01-07T16:42:33.619667Z") + sharedSecret;
//Encoding saltedString using Unicode little-endian byte order
byte[] encodedSaltedString = Encoding.Unicode.GetBytes(saltedString);
//Hashing Algorithm used is SHA512
HashAlgorithm hash = new SHA512Managed();
//Compute Hash of encodedSaltedString
byte[] hashedEncodedString = hash.ComputeHash(encodedSaltedString);
//Convert hashed array to base64-encoded string
string signature = Convert.ToBase64String(hashedEncodedString);
I am then getting this result in C#:
"gQhjrLnY6fo44EeaaWaUBE1PY/8oEIRsUcK3AMSCVUCYMM4vRfxvQEEggXaHTF0GQbw4w2HbWArX1k6NnkzJFg=="
I converted to this code as below, but I am getting an issue. Can I get some help on this?
$timestamp = "2021-01-07T16:42:33.619667Z";
$sharedSecret = 'xx';
$saltedString = $timestamp.$sharedSecret;
$utf=mb_convert_encoding($saltedString, "UTF-16LE");
$signature = base64_encode(hash('sha512', $utf));
IN PHP I am getting this result:
ODEwODYzYWNiOWQ4ZTlmYTM4ZTA0NzlhNjk2Njk0MDQ0ZDRmNjNmZjI4MTA4NDZjNTFjMmI3MDBjNDgyNTU0MDk4MzBjZTJmNDVmYzZmNDA0MTIwODE3Njg3NGM1ZDA2NDFiYzM4YzM2MWRiNTgwYWQ3ZDY0ZThkOWU0Y2M5MTY=
But both should be same. The c# one is correct, I want the same in the php code as well.
From the PHP docs for hash:
hash ( string $algo , string $data , bool $binary = false ) : string|false
binary
When set to true, outputs raw binary data. false outputs lowercase hexits.
You're not passing a value for $binary, so it's returning a string of hexadecimal characters.
The C# HashAlgorithm.ComputeHash method on the other hand binary data.
Since you're base64-encoding the result, you're presumably expecting the hash function to return binary data. You therefore need to pass true as the value for $binary:
$signature = base64_encode(hash('sha512', $utf, true));
Is it byte inside the session or data will be converted into the string after writing?
if yes I think I can take it like this:
var res = Encoding.UTF8.GetBytes(Session["session_state"]);
or can I take it "as is" without converting into the byte array? like:
var res = Session["session_state"] as bytes[]; // or smth. like that
The data isn't converted. If the session object is serialized (depending on how it is stored), then it is deserialized before you get access to it again.
Just cast the value to a byte array:
var res = Session["session_state"] as byte[];
or:
var res = (byte[])Session["session_state"];
Side note: A byte array can't reliably be converted to a string using UTF-8 encoding. UTF-8 is used the other way around, i.e. converting a string to bytes and then back. To make a string from bytes you would rather use something like base64.
You will always get what you stored in the session regardless of the mode you are using for the session state (inproc, state server, ...)
So the answer will be
var res = Session["session_state"] as byte[];
I'm working on a client that should communicate with an MMO game server.
The client is using unity3d.
I get the data from the server with JSON format and I try to get the data in UTF8 encoding:
string responseString = new System.IO.StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8).ReadToEnd()
JSONObject JOBJ = new JSONObject(responseString);
and what is inside the response string looks like:
"\u0645\u0639\u062f\u0646 \u062a\u06cc\u062a\u0627\u0646\u06cc\u0648\u0645"
Then I try to get the required utf8 string data out of the JSON:
string xy = JOBJ["name"].ToString();
byte[] utf = System.Text.Encoding.UTF8.GetBytes(xy);
string s2= System.Text.Encoding.UTF8.GetString(utf);
The Problem is when I Log the string:
Debug.Log("Jproperty :" + s2);
All I get is the \u secuences like this:
"\u0645\u0639\u062f\u0646 \u062a\u06cc\u062a\u0627\u0646\u06cc\u0648\u0645"
While if I put the same result in the xy in the first place I'll get the fine result.
Also I should mention that while I think that the s2.length should be 11 it is 66.
Any one can tell me what's wrong with my code?
Strings that contain unicode escape sequences are perfectly valid. Your data might be getting escaped before it is sent to the server.
Try Regex.Unescape:
var nameEscaped = JOBJ["name"].ToString();
// nameEscaped =
// \u0645\u0639\u062f\u0646 \u062a\u06cc\u062a\u0627\u0646\u06cc\u0648\u0645
var name = Regex.Unescape(nameEscaped);
// name =
// معدن تیتانیوم
I'm working on implementing a hosted checkout, and the hosted checkout is supposed to redirect the user back to my website so that I can show a custom receipt page.
This is a sample querystring that I'd get back:
trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=&hashValue=33dacf84682470f267b2cc6d528b1594
To validate the request, I'm supposed to remove &hashValue=f3cf58ef0fd363e0c2241938b04f1068 from the end of the querystring, and then append a key. I then perform an MD5 hash of the entire string, and the result should be 33dacf84682470f267b2cc6d528b1594, same as the original.
This is easy, except that a few of the fields are causing a problem for me. This is the code I use (taken from a dummy application, so you can ignore some of the bad coding):
// Split up the query string parameters
string[] parameters = GetQueryString().Split(new[] { "&" }, StringSplitOptions.None);
var querySet = new List<string>();
// Rebuild the query string, encoding the values.
foreach (string s in parameters)
{
// Every field that contains a "." will need to be encoded except for trnAmount
querySet.Add(param.Contains("trnAmount") ? param : UrlEncodeToUpper(param));
}
// Create the querystring without the hashValue, we need to calculate our hash without it.
string qs = string.Join("&", querySet.ToArray());
qs = qs.Substring(0, qs.IndexOf("&hashValue"));
qs = qs + "fb76124fea73488fa11995dfa4cbe89b";
var encoding = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(encoding.GetBytes(qs));
var calculatedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLower();
This is the UrlEncode method I use.
private static string UrlEncodeToUpper(string value)
{
// Convert their encoding into uppercase so we can do our hash
value = Regex.Replace(value, "(%[0-9af][0-9a-f])", c => c.Value.ToUpper());
// Encode the characters that they missed
value = value.Replace("-", "%2D").Replace(".", "%2E").Replace("_", "%5F");
return value;
}
This all works (until someone enters a character I haven't accounted for), except this seems more complicated than it should be. I know I'm not the only one who has to implement this HCO into an ASP.NET application, so I don't think the simple validation should be so complicated.
Am I missing an easier way to do this? Having to loop through the fields, encoding some of them while skipping others, converting their encoding to uppercase and then selectively replacing characters seems a little... odd.
Here's a better way to work with query strings:
var queryString = "trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=&hashValue=33dacf84682470f267b2cc6d528b1594";
var values = HttpUtility.ParseQueryString(queryString);
// remove the hashValue parameter
values.Remove("hashValue");
var result = values.ToString();
// At this stage result = trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=
// now add some other query string value
values["foo"] = "bar"; // you can stuff whatever you want it will be properly url encoded
Then I didn't quite understand what you wanted to do. You want to calculate an MD5 on the result? You could do that and then append to the query string.
I need to express a collection of about 10-15 short strings (and maybe some ints) as a fairly compact alphanumeric string - one which I can send as a parameter in a get request.
Basically, I'm thinking that my collection will be a hashtable, and I'd like to serialize it so it looks sort of like a viewstate string (only hopefully not so long!).
eg.
testpage.aspx?code=rO0ABXNyAAlTb21lQ2xhc3PSHbLk6OgfswIAA0kAAWl
and then testpage.aspx can deserialize this back to the original collection.
Is this possible?
One option here is to pick a delimiter, for example ¤; join the strings, encode them (perhaps UTF8), and pack the bytes as base-64...
string[] data = {"abc","123", "def"};
string s = string.Join("¤", data);
byte[] raw = Encoding.UTF8.GetBytes(s);
string alphaNumeric = Convert.ToBase64String(raw); // send this
(you may need to handle the few non-alphanumeric characters that base-64 uses).
And to reverse it:
raw = Convert.FromBase64String(alphaNumeric);
s = Encoding.UTF8.GetString(raw);
data = s.Split('¤');
If you want to send key/value pairs... well, the obvious choice would be query-string parameters themselves, since they are designed for this. But if you need it as a byte-stream:
var data = new DbConnectionStringBuilder();
data["foo"] = "abc";
data["bar"] = "123 + ;la";
string s = data.ConnectionString;
byte[] raw = Encoding.UTF8.GetBytes(s);
string alphaNumeric = Convert.ToBase64String(raw); // send this
raw = Convert.FromBase64String(alphaNumeric);
s = Encoding.UTF8.GetString(raw);
data.ConnectionString = s;
foreach (string key in data.Keys)
{
Console.WriteLine(key + "=" + data[key]);
}
Why don't you just serialize the data using protobuf-net and pass it through the Session? Or, if it has to be a string, just use XmlSerializer?
Personally, passing serialized data through the URL seems really bad to me!
you can serialize your dictionary/hashtable to JSON,
and then change it to base64 (just to make it a tad less visible and resolve possible usage of URL characters etc).
or you can just URLEncode it.
You can use standard .Net serialization and serialize your object to a MemoryStream. You can then read out the contents of the MemoryStream as a byte array and use Convert.ToBase64String on the array to get a string representation of it.
To deserialize it you can do the opposite.
If you are worried that the serialized object is too large, you can wrap the MemoryStream in a System.IO.Compression.DeflateStream to compress it.
Thank you all, putting it together I wrote a test console app. I was a bit disappointed that the resulting string was so long.
My example implements a DeflateStream, which for my datasize probably introduces more overhead than it saves with compression. But even without the compression it was still pretty big.
What I was hoping to achieve was to make something slightly more compact (obfuscation for the user was a plus, but not critical) - I suspect that it'd actually be better for me to use a plain old parameterized string. Maybe JSON might be ok, but I'm using ASP.net 2.0, and I don't think that I get a readybaked json serializer there.
Nonetheless, I learnt something new and interesting, so thanks for that!
static void Main(string[] args)
{
Hashtable ht1 = new Hashtable(1);
ht1.Add("name", "bob");
Console.WriteLine(ToCompactString(ht1));
Console.WriteLine();
string str = "name:bob";
Console.WriteLine(ToCompactString(str));
Console.ReadLine();
}
private static string ToCompactString(object obj)
{
var ms = new MemoryStream();
var ds = new DeflateStream(ms, CompressionMode.Compress);
var bf = new BinaryFormatter();
bf.Serialize(ds, obj);
byte[] bytes = ms.ToArray();
ds.Close();
ms.Close();
string result = Convert.ToBase64String(bytes);
return result;
}