NSData Sha512 Hashing with Xamarin - xamarin

I have an example of SHA512 hash of two NSData objects (Objective-C)
Objective C SHA512 hash of two NSData
that's in objective C, using the CommonCrypto, however I have tried to do the same thing using the SHA512Managed Class but could not get the same results.
PS: I am looking to be able to hash 2 NSData objects not a string.
Is there any way to do it using C#?
What would be the equivalent of CC_SHA512_Update and CC_SHA512_Final for Xamarin.iOS?

You could create the NSData with the string .
SHA512 shaM = new SHA512Managed();
byte[] data = shaM.ComputeHash(Encoding.UTF8.GetBytes(""));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
string stringyHash = sBuilder.ToString();
NSData dataStr = NSData.FromString(stringyHash,NSStringEncoding.UTF8);

I think, I've found the answer:
To reproduce the same output as the native code mentioned in my question
I would use the following method:
public NSData SHA512HashWithSalt(NSData contentData, NSData saltData)
{
HashAlgorithm algorithm = new SHA256Managed();
//Convert NSData to array of bytes
byte[] salt = saltData.ToArray();
byte[] content = contentData.ToArray();
byte[] plainTextWithSaltBytes =
new byte[content.Length + salt.Length];
for (int i = 0; i < content.Length; i++)
{
plainTextWithSaltBytes[i] = content[i];
}
for (int i = 0; i < salt.Length; i++)
{
plainTextWithSaltBytes[content.Length + i] = salt[i];
}
return NSData.FromArray(algorithm.ComputeHash(plainTextWithSaltBytes));
}

Related

Is there a way to avoid the truncation of attached properties when using Appcenter with Xamarin?

Here's my code:
Crashes.TrackError(ex,
new Dictionary<string, string> {
{"RunQuery", "Exception"},
{"sql", s },
{"Device Model", DeviceInfo.Model },
{"Exception", ex.ToString()}
});
Everything works but I find that Appcenter limits the length of the parameters to 125 characters so it's useless for me as I can never see all of the sql or the ex string.
Has anyone found a way to get around this?
I ran into the same problem. My solution was to break my string into groups of 125 character strings and iterate through while logging. I chatted with AppCenter support. They have no way of extending this length currently.
Here is a scrubbed version of my code:
var tokenChunks = LoggingHelper.SplitBy(extremelyLongString, 120);
string title = "Long string here";
var props = new Dictionary<string, string>();
int item = 0;
foreach(string chunk in tokenChunks)
{
string chunkIndex = string.Format("item: {0}", item++);
props.Add(chunkIndex, chunk);
}
Analytics.TrackEvent(title, props);
Where the LoggingHelper class is:
public static class LoggingHelper
{
public static IEnumerable<string> SplitBy(this string str, int chunkLength)
{
if (String.IsNullOrEmpty(str)) throw new ArgumentException();
if (chunkLength < 1) throw new ArgumentException();
for (int i = 0; i < str.Length; i += chunkLength)
{
if (chunkLength + i > str.Length)
chunkLength = str.Length - i;
yield return str.Substring(i, chunkLength);
}
}
}
I should give credit to this post https://stackoverflow.com/a/8944374/117995 by #oleksii for the SplitBy method.

Morse code conversion on how to return a method

Please pardon me for my weak porgramming ability. I'm trying to write a method converting english to morse code. As you can see, I use hashmap to store the equivalant and then convert it and stored the morse code into the variable 'result'. My concern is I can't return the variable 'result' outside of the loop. If i return 'dataInput', isn't it just returning the original input? How can I return the correct result?
public static String morseCode(String dataInput)
{
Map<String, String> morseCode = new HashMap<String, String>();
morseCode.put("a", ".-");
morseCode.put("b", "-...");
morseCode.put("c", "-.-.");
for (int i = 0; i<dataInput.length(); i++)
{
String result = (String)morseCode.get(dataInput.charAt(i)+"");
//convert input data into morse code
}
return dataInput;
}
Try like this:
import java.lang.StringBuffer; //at the top
Map morseCode = new HashMap();
morseCode.put("a", ".-");
morseCode.put("b", "-...");
morseCode.put("c", "-.-.");
StringBuffer buff = new StringBuffer();
for (int i = 0; i<dataInput.length(); i++)
{
String result = (String)morseCode.get(dataInput.charAt(i));
//convert input data into morse code
buff.append(result+" ");
}
return buff.toString();
}

How replace a phrase using charAt()?

I am having trouble with this method. It is supposed to receive a sentence (word) and replace any instance of dang with #!.
It works in some cases but when the input is "dang boom dang" the output is #! boom da#!.
Does anyone have any suggestions on how to fix this?
Here is my code so far:
public static String deleteDang(String word)
{
StringBuffer wordSB = new StringBuffer(word);
int length = wordSB.length();
for (int i = 0; i < length; i++)
{
if (word.charAt(i)=='d'|| word.charAt(i)=='D')
if (word.charAt(i+1)=='a'|| word.charAt(i+1)=='A')
if (word.charAt(i+2)=='n'|| word.charAt(i+2)=='N')
if (word.charAt(i+3)=='g'|| word.charAt(i+3)=='G')
wordSB = wordSB.replace(i,i+4, "#!");
length = wordSB.length();
}
String newWord = wordSB.toString();
return newWord;
}
In your for loop replace all references to word with wordSB
public static String deleteDang(String word)
{
StringBuffer wordSB = new StringBuffer(word);
int length=wordSB.length();
for (int i=0; i<length; i++)
{
if (wordSB.charAt(i)=='d'|| wordSB.charAt(i)=='D')
if (wordSB.charAt(i+1)=='a'|| wordSB.charAt(i+1)=='A')
if (wordSB.charAt(i+2)=='n'|| wordSB.charAt(i+2)=='N')
if (wordSB.charAt(i+3)=='g'|| wordSB.charAt(i+3)=='G')
wordSB = wordSB.replace(i,i+4, "#!");
length=wordSB.length();
}
String newWord= wordSB.toString();
return newWord;
}
That way you reference the updated array when you do a replace

AS-3 - How To Insert A ByteArray In Another ByteArray

I would like to insert a ByteArray anywhere in between another ByteArray
var main: ByteArray = ...;
var bytes2insert: ByteArray = ...;
var index: int = ...;
// index is 0 to main.length and tells me where to write the bytes2insert in main
main.writeBytes(bytes2insert, index, bytes2insert.length);
If I try writeBytes with random index I get errors because of "IndexOutOfBounds" and stuff. How can I achieve the inserting ? I will probably get away with some for-loops but for performance reasons I would like to (mostly) use given methods.
EDIT: I think the AS-3 documentation is a bit lacky (didn't check adobe.com though)
// since the script needs to read from bytes2insert and write to main
// main.writeBytes(array, offset, length);
main.position = <start index for writing> // (seems to be important in this case)
offset = <start index for reading> // (I misunderstood that one)
length = <length for both>
Solution:
public function astest()
{
var main: ByteArray = new ByteArray();
var bytes2insert: ByteArray = new ByteArray();
var index: int = 5;
for(var i:int = 0; i < 20; i++)
main.writeByte(99);
for(var j:int = 0; j < 30; j++)
bytes2insert.writeByte(100);
trace("1", main);
insertBytes(main, bytes2insert, index);
trace("2", main);
}
private function insertBytes(target:ByteArray, insert:ByteArray, index:int):void
{
if(index < target.length)
{
var tmp:ByteArray = new ByteArray();
tmp.writeBytes(target, index);
target.position = index;
target.writeBytes(insert);
target.writeBytes(tmp);
}
}
//output:
//1 cccccccccccccccccccc
//2 cccccddddddddddddddddddddddddddddddccccccccccccccc

SHA1 with salt on windows phone 7

I have some some time now reshearchd how to encode a password to SHA1 with a salt.
The is the code i used on my web application part, but it will not work on a phone environment.
public class Password
{
private string _password;
private int _salt;
public Password(string strPassword, int nSalt)
{
_password = strPassword;
_salt = nSalt;
}
public string ComputeSaltedHash()
{
// Create Byte array of password string
ASCIIEncoding encoder = new ASCIIEncoding();
Byte[] _secretBytes = encoder.GetBytes(_password);
// Create a new salt
Byte[] _saltBytes = new Byte[4];
_saltBytes[0] = (byte)(_salt >> 24);
_saltBytes[1] = (byte)(_salt >> 16);
_saltBytes[2] = (byte)(_salt >> 8);
_saltBytes[3] = (byte)(_salt);
// append the two arrays
Byte[] toHash = new Byte[_secretBytes.Length + _saltBytes.Length];
Array.Copy(_secretBytes, 0, toHash, 0, _secretBytes.Length);
Array.Copy(_saltBytes, 0, toHash, _secretBytes.Length, _saltBytes.Length);
SHA1 sha1 = SHA1.Create();
Byte[] computedHash = sha1.ComputeHash(toHash);
return encoder.GetString(computedHash);
}
public static int CreateRandomSalt()
{
Byte[] _saltBytes = new Byte[4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(_saltBytes);
return ((((int)_saltBytes[0]) << 24) + (((int)_saltBytes[1]) << 16) +
(((int)_saltBytes[2]) << 8) + ((int)_saltBytes[3]));
}
public static string CreateRandomPassword(int PasswordLength)
{
String _allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ23456789!\"#ยค%&/()=?$+-_.,;'*";
Byte[] randomBytes = new Byte[PasswordLength];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
char[] chars = new char[PasswordLength];
int allowedCharCount = _allowedChars.Length;
for (int i = 0; i < PasswordLength; i++)
{
chars[i] = _allowedChars[(int)randomBytes[i] % allowedCharCount];
}
return new string(chars);
}
}
Silverlight and Windows Phone 7 do not have an ASCIIEncoding. I suggest you use the UTF8Encoding instead. If you are certain that your passwords are always within the ASCII range then this encoding will work the same as the ASCIIEncoding would of had it been present.
If on the other hand you cannot guarantee that passwords are always within the ASCII range then you would need to make sure both ends hash using the UTF8Encoding to ensure generated hashs are the same.

Resources