Generating SHA256 in Swift (iOS) - c#

I am trying to generate SHA256 using the following function:-
func generateHMAC(key: String, data: String) -> String {
let keyData = key.dataFromHexadecimalString()! as NSData
let dataIn = data.dataUsingEncoding(NSUTF16StringEncoding)
var result: [CUnsignedChar]
result = Array(count: Int(CC_SHA256_DIGEST_LENGTH), repeatedValue: 0)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, keyData.length, dataIn!.bytes, dataIn!.length, &result)
let hash = NSMutableString()
for val in result {
hash.appendFormat("%02hhx", val)
}
return hash as String
}
Input is
AccountNumber: 100195
Amount: 10
BillerID: 59
ChannelID: 2
Context: 11|test
CountryID: 1
CustomerID: 34
EmailID: ankur.arya#me.com
ReturnURL: https://uat.myfatoora.com/ReceiptPOC.aspx
SECURITYTOKEN: 6B4A47A6-40A0-4C9D-A925-5CECA2910881
TxnRefNum: 991107844408242
UserName: USP
and the output is
4cd1acc736a9702c8cdb1a546d1c274a67cb285dbdbb972aab39ee51c2a2‌​26c8
However, this doesn’t match with the output of backend which uses the following algo
private string CreateSHA256POC(bool useRequest)
{
// Hex Decode the Secure Secret for use in using the HMACSHA256 hasher
// hex decoding eliminates this source of error as it is independent of the character encoding
// hex decoding is precise in converting to a byte array and is the preferred form for representing binary values as hex strings.
secureHash = "";
byte[] convertedHash = new byte[_secureSecret.Length / 2];
for (int i = 0; i < _secureSecret.Length / 2; i++)
{
convertedHash[i] = (byte)Int32.Parse(_secureSecret.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
// Build string from collection in preperation to be hashed
StringBuilder sb = new StringBuilder();
SortedList<String, String> list = (useRequest ? requestFields : responseFields);
foreach (KeyValuePair<string, string> kvp in list)
{
// if (kvp.Key.StartsWith("vpc_") || kvp.Key.StartsWith("user_"))
sb.Append(kvp.Key + "=" + kvp.Value + "&");
}
// remove trailing & from string
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);
// Create secureHash on string
string hexHash = "";
using (HMACSHA256 hasher = new HMACSHA256(convertedHash))
{
byte[] hashValue = hasher.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
foreach (byte b in hashValue)
{
hexHash += b.ToString("X2");
secureHash = hexHash;
}
}
return hexHash;
}
and their output is
41D8E81C128100A76185F24CE00BC6A4FEA30839E6DE3DFFBC3B5814E4FD0C4E
Secret key is
71DD0F73AFFBB47825FF9864DDE95F3B
Can you please help me to update my method in Swift to get the same result as backend.
Thanks.

Related

How to XOR a MD5 hash and return a 32 character string?

How do I further encrypt a MD5 hash by XOR'ing it with a string of variable size (not bigger than 32 characters) ?
I would like the result of the XOR to be a 32 character string as well.
What i have tried so far is:
convert the md5 string to binary
convert second string to binary
pad second binary with 0's (to the left) until both binaries are of equal length
iterate the binary representations and XOR them
convert the XOR'ed result to a string
The approach may be wrong, im not sure how to do it. My problem is, when converting the result of the XOR, it is not a 32 character long string, as I would like it to be.
Sample code (equal length strings in this case):
class Program
{
static void Main(string[] args)
{
var md51 = ToBinary(ConvertToByteArray(CalculateMD5Hash("Maaa"), Encoding.ASCII));
var md52 = ToBinary(ConvertToByteArray(CalculateMD5Hash("Moo"), Encoding.ASCII));
List<int> xoredResult = new List<int>();
for (int i = 0; i < md51.Length; i++)
{
var string1 = md51[i];
var string2 = md52[i];
var xor = string1 ^ string2;
xoredResult.Add(xor);
}
var resultingString = string.Join("", xoredResult);
Console.WriteLine(resultingString.Length);
var data = GetBytesFromBinaryString(resultingString);
var text = Encoding.ASCII.GetString(data);
}
public static byte[] ConvertToByteArray(string str, Encoding encoding)
{
return encoding.GetBytes(str);
}
public static String ToBinary(Byte[] data)
{
return string.Join("", data.Select(byt => Convert.ToString(byt, 2).PadLeft(8, '0')));
}
public static Byte[] GetBytesFromBinaryString(String binary)
{
var list = new List<Byte>();
for (int i = 0; i < binary.Length; i += 8)
{
String t = binary.Substring(i, 8);
list.Add(Convert.ToByte(t, 2));
}
return list.ToArray();
}
public static string CalculateMD5Hash(string input)
{
// step 1, calculate MD5 hash from input
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
}
xoring a string with what is essentially random bytes is not guaranteed to give you a valid string as a output. Your var text = Encoding.ASCII.GetString(data); is likely failing because you are passing it a non valid string in byte form. You must use something like var text = Convert.ToBase64String(data) to be able to represent the random data without loss of information in the process.

MD5 hash special characters

I have tried hashing a string in PHP using MD5 and the same in C#, but the results are different if the string contains special characters. Can someone explain me how to get this matched?
Here is my code in C#:
MD5 md5 = new MD5CryptoServiceProvider();
//compute hash from the bytes of text
md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(text));
//get hash result after compute it
byte[] result = md5.Hash;
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
//change it into 2 hexadecimal digits
//for each byte
strBuilder.Append(result[i].ToString("x2"));
}
return strBuilder.ToString();
My string is "Samuel2989&*" as a string.
Outputs:
PHP: 957915b9c9a8fb65e13fe1dc9a8b86d4
C# : f5ee451f7eb4587da00d4aa31ae1c378
Can you try with this method and tell me if it worked out for you?
public static string MD5Hash(string input)
{
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
bs = x.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in bs)
{
s.Append(b.ToString("x2").ToLower());
}
string password = s.ToString();
return password;
}

C#: How do i modify this code to split the string with hyphens?

Hello i need some help modifying this code so it splits this string with hyphens:
string KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
I would like to lay it out like this:
1234-1234-1234-1234
with a char length of 4 per segment and max chars about 16
Full Code
private static string GetKey()
{
char[] chars = new char[62];
string KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
chars = KeyString.ToCharArray();
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
byte[] data = new byte[1];
crypto.GetNonZeroBytes(data);
data = new byte[8];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(8);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length - 1)]);
}
return result.ToString();
}
the code is used for generating random ids
any help would be appreciated
Can't... resist... regex... solution
string KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
Console.WriteLine(
new System.Text.RegularExpressions.Regex(".{4}")
.Replace(KeyString, "$&-").TrimEnd('-'));
outputs
abcd-efgh-ijkl-mnop-qrst-uvwx-yzAB-CDEF-GHIJ-KLMN-OPQR-STUV-WXYZ-1234-5678-90
But yes, if this is a Guid, by all means, use that type.
How about:
StringBuilder result = new StringBuilder();
for (var i = 0; i < data.Length; i++)
{
if (i > 0 && (i % 4) == 0)
result.Append("-");
result.Append(chars[data[i] % (chars.Length - 1)]);
}
result.Length -= 1; // Remove trailing '-'
It might be worthwhile to have a look into Guid, it produces strings in the format xxxxxxxx-xxxx-xxxx-xxxxxxxx (32 chars) if you definitely want 16 chars, you could take some 16 chars in the middle of the 32 generated by Guid.
Guid guid = Guid.NewGuid(); /* f.e.: 0f8fad5b-d9cb-469f-a165-70867728950e */
string randomid = guid.ToString().Substring(4, 19);

PHP Equivalent to C# GetBytesFromUTF8

I am trying to create a php function thats will allow me access to a dotnet single sign on system and I am hung up on finding a php equivalent to GetBytesFromUTF8, I have tried ord and mb_string to no avail. Any ideas for a php equivalent to the C# GetBytesFromUTF8?
//Function to Create the SSO function SSO($key,$uid){ $lenth=32; $aZ09 = array_merge(range('A', 'Z'), range('a', 'z'),range(0, 9)); $randphrase ='';
for($c=0;$c < $lenth;$c++) {
$randphrase .= $aZ09[mt_rand(0,count($aZ09)-1)];
}
//Append key onto phrase end
$randkey=$randphrase.$key;
//Number of Bytes is string (THIS IS THE PROBLEM, ITS JUST ADDING THE STRING LENGTH)
$bytevalue=mb_strlen($randkey, 'latin1');
// SHA512 Hash
//$toencode= utf8_encode($bytevalue);
$output = hash("sha512", $bytevalue);
//base 64 encode the hash
$sso = base64_encode($output);
$length = mb_strlen($sso);
$characters = 2;
$start = $length - $characters;
$last2 = substr($sso , $start ,$characters);
//$startitup = APIClient::Create('http://my.staging.dosespot.com/LoginSingleSignOn.aspx','SingleSignOnCode=$ssocode');
// Yes, Strip the extra ==
if($last2 == "=="){$ssocode = substr($sso,0,-2);}
// No, just pass the value to the next step
else{$ssocode=$sso;}
//Use first 22 charecters of random.
$shortphrase=substr($randphrase,0,22);
//Append uid & key onto shortened phrase end
$uidv=$uid.$shortphrase.$key;
//Number of Bytes is string
$idbytevalue=mb_strlen($uidv, 'latin1');
//$idbytevalue= strBytes(utf8_encode($uidv));
// SHA512 Hash
$idencode= utf8_encode($idbytevalue);
$idoutput = hash("sha512", $idencode);
// Base64 Encode of hash
$idssoe = base64_encode($idoutput);
//Determine if we need to strip the zeros
$idlength = mb_strlen($idssoe);
$idcharacters = 2;
$idstart = $idlength - $idcharacters;
$idlast2 = substr($idssoe , $idstart ,$idcharacters);
if($idlast2 == "=="){$ssouidv = substr($idssoe,0,-2);}
// No, just pass the value to the next step
else{$ssouidv=$idssoe;}
return array($ssocode, $ssouidv);
}
I am trying to replicate this c#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DoseSpot.EncryptionLibrary
{
public class EncodingUtility
{
public enum encodingOptions : int
{
ASCII = 0,
UTF7,
UTF8,
UTF32,
Unicode,
Base64String
}
public static string GetString(byte[] data, encodingOptions eo)
{
switch (eo)
{
case encodingOptions.ASCII:
return ToASCII(data);
case encodingOptions.Unicode:
return ToUnicode(data);
case encodingOptions.Base64String:
return ToBase64String(data);
case encodingOptions.UTF7:
return ToUTF7(data);
case encodingOptions.UTF32:
return ToUTF32(data);
case encodingOptions.UTF8:
default:
return ToUTF8(data);
}
}
public static byte[] GetBytes(string message, encodingOptions eo)
{
switch (eo)
{
case encodingOptions.ASCII:
return FromASCII(message);
case encodingOptions.Unicode:
return FromUnicode(message);
case encodingOptions.Base64String:
return FromBase64String(message);
case encodingOptions.UTF7:
return FromUTF7(message);
case encodingOptions.UTF32:
return FromUTF32(message);
case encodingOptions.UTF8:
default:
return FromUTF8(message);
}
}
protected static string ToBase64String(byte[] data)
{
return Convert.ToBase64String(data);
}
protected static string ToUnicode(byte[] data)
{
return unicode.GetString(data);
}
protected static string ToASCII(byte[] data)
{
return ascii.GetString(data);
}
protected static string ToUTF7(byte[] data)
{
return utf7.GetString(data);
}
protected static string ToUTF8(byte[] data)
{
return utf8.GetString(data);
}
protected static string ToUTF32(byte[] data)
{
return utf32.GetString(data);
}
protected static byte[] FromBase64String(string originalString)
{
return Convert.FromBase64String(originalString);
}
protected static byte[] FromUnicode(string originalString)
{
return unicode.GetBytes(originalString);
}
protected static byte[] FromASCII(string originalString)
{
return ascii.GetBytes(originalString);
}
protected static byte[] FromUTF7(string originalString)
{
return utf7.GetBytes(originalString);
}
protected static byte[] FromUTF8(string originalString)
{
return utf8.GetBytes(originalString);
}
protected static byte[] FromUTF32(string originalString)
{
return utf32.GetBytes(originalString);
}
public static Encoding getEncoding(encodingOptions eo)
{
switch (eo)
{
case encodingOptions.ASCII:
return ascii;
case encodingOptions.UTF7:
return utf7;
case encodingOptions.UTF8:
return utf8;
case encodingOptions.UTF32:
return utf32;
case encodingOptions.Unicode:
default:
return unicode;
}
}
private static ASCIIEncoding ascii = new ASCIIEncoding();
private static UTF8Encoding utf8 = new UTF8Encoding();
private static UTF7Encoding utf7 = new UTF7Encoding();
private static UTF32Encoding utf32 = new UTF32Encoding();
private static UnicodeEncoding unicode = new UnicodeEncoding();
}
}
public static class EncryptionCommon
{
public static int KeyLength = 32;
public static int PhraseLength = 32;
public static string CreatePhrase()
{
return Randomizer.RandomNumberOfLettersAll(PhraseLength);
}
public static string CreateKey()
{
return Randomizer.RandomNumberOfLetters(KeyLength);
}
public static string Encrypt(string Phrase, string MyKey)
{
byte[] data = EncodingUtility.GetBytes(Phrase + MyKey, EncodingUtility.encodingOptions.UTF8);
byte[] result = new SHA512Managed().ComputeHash(data);
string tempString = EncodingUtility.GetString(result, EncodingUtility.encodingOptions.Base64String);
if (tempString.Substring(tempString.Length - 2).ToString().Equals("=="))
tempString = tempString.Substring(0, tempString.Length - 2);
return tempString;
}
public static string EncryptUserId(string Phrase, int UserId, string MyKey)
{
string UserPhrase = UserId.ToString();
if (Phrase.Length > 22)
UserPhrase += Phrase.Substring(0, 22);
else
UserPhrase += Phrase;
return Encrypt(UserPhrase, MyKey);
}
public static bool VerifyKey(string key, string combinedPhraseAndEncryptedString)
{
Dictionary<string, string> myDict = SplitStringIntoPhraseAndHash(combinedPhraseAndEncryptedString);
string phrase = myDict["phrase"];
string providedEncryptedPhrase = myDict["encryptedString"];
string testEncryptedPhrase = Encrypt(phrase, key);
if (providedEncryptedPhrase.Equals(testEncryptedPhrase))
return true;
else
return false;
}
public static Dictionary<string, string> SplitStringIntoPhraseAndHash(string stringToSplit)
{
Dictionary<string, string> myResult = new Dictionary<string, string>();
if (stringToSplit != null && stringToSplit.Trim().Length >= PhraseLength)
{
string phraseFound = stringToSplit.Substring(0, PhraseLength);
string encryptedString = stringToSplit.Substring(PhraseLength);
myResult.Add("phrase", phraseFound);
myResult.Add("encryptedString", encryptedString);
}
return myResult;
}
public static string CreatePhraseEncryptedCombinedString(string phrase, string key)
{
string toReturn = phrase;
toReturn += Encrypt(phrase, key);
return toReturn;
}
}
I am trying to replicate this C# process in PHP to no avail.
HOW TO CREATE THE CORRECT SINGLESIGNONCODE:
1. You have been provided a key (in UTF-8)
2. Create a random phrase 32 characters long in UTF-8
a. Create32CharPhrase
3. Append the key to the phrase
a. Create32CharPhrase + Key
4. Get the value in Bytes from UTF-8 String
a. GetBytesFromUTF8(Create32CharPhrase + Key)
5. Use SHA512 to hash the byte value you just received
SHA512Hash(GetBytesFromUTF8(Create32CharPhrase + Key))
6. Get a Base64String out of the hash that you created
GetBase64String(SHA512Hash(GetBytesFromUTF8(Create32CharPhrase + Key)))
7. If there are two = signs at the end, then remove them.
RemoveExtraEqualsSigns(GetBase64String(SHA512Hash(GetBytesFromUTF8(Create32CharPhrase
+ Key))))
The Second part of the function...
HOW TO CREATE THE CORRECT SINGLESIGNONUSERIDVERIFY:
1. Grab the first 22 characters of the phrase from step 1
2. Append to the UserId string the 22 characters grabbed from step one
3. (UserId) + (first 22 characters of phrase)
4. Append the key to the string created in 2b
(UserId) +(first 22 characters of phrase) + key
5. Get the Byte value of the string
GetBytesFromUTF8((UserId) + (first 22 characters of phrase) + key)
6. Use SHA512 to hash the byte value you just received
SHA512Hash(GetBytesFromUTF8((UserId) + (first 22 characters of phrase) + key))
7. Get a Base64String out of the hash that you created
8. GetBase64String(SHA512Hash(GetBytesFromUTF8((UserId) + (first 22 characters of phrase) +
key)))
9. If there are two = signs at the end, then remove them.
RemoveExtraEqualsSigns(GetBase64String(SHA512Hash(GetBytesFromUTF8((UserId) + (first 22
characters of phrase) + key))))
Taken out of an edit to the original post
PHP SSO for ASP service
function SSO($key,$uid){
$lenth=32;
$aZ09 = array_merge(range('A', 'Z'), range('a', 'z'),range(0, 9));
$randphrase ='';
for($c=0;$c < $lenth;$c++) {
$randphrase .= $aZ09[mt_rand(0,count($aZ09)-1)];
}
//echo "Key: ".$key."<br/>";
//echo "Phrase: ".$randphrase."<br/>";
//Append key onto phrase end
$randkey=$randphrase.$key;
// SHA512 Hash
$toencode= utf8_encode($randkey);
// Pass 3rd, optional parameter as TRUE to output raw binary data
$output = hash("sha512", $toencode, true);
//base 64 encode the hash binary data
$sso = base64_encode($output);
$length = mb_strlen($sso);
$characters = 2;
$start = $length - $characters;
$last2 = substr($sso , $start ,$characters);
// Yes, Strip the extra ==
if($last2 == "==")
{$ssocode = substr($sso,0,-2);}
// No, just pass the value to the next step
else{$ssocode=$sso;}
// Prepend the random phrase to the encrypted code.
$ssocode = $randphrase.$ssocode;
//echo "SSO: ".$ssocode."<br/>";
//Use first 22 charecters of random.
$shortphrase=substr($randphrase,0,22);
//Append uid & key onto shortened phrase end
$uidv=$uid.$shortphrase.$key;
// SHA512 Hash
$idencode= utf8_encode($uidv);
// Pass 3rd, optional parameter as TRUE to output raw binary data
$idoutput = hash("sha512", $idencode, true);
// Base64 Encode of hash binary data
$idssoe = base64_encode($idoutput);
//Determine if we need to strip the zeros
$idlength = mb_strlen($idssoe);
$idcharacters = 2;
$idstart = $idlength - $idcharacters;
$idlast2 = substr($idssoe , $idstart ,$idcharacters);
if($idlast2 == "==")
{$ssouidv = substr($idssoe,0,-2);}
// No, just pass the value to the next step
else{$ssouidv=$idssoe;}
//echo "SSOID: ".$ssouidv;
return array($ssocode, $ssouidv);
}

Binary to Text Translation C# [duplicate]

Hi i was able to convert a ASCII string to binary using a binarywriter .. as 10101011 . im required back to convert Binary ---> ASCII string .. any idea how to do it ?
This should do the trick... or at least get you started...
public Byte[] GetBytesFromBinaryString(String binary)
{
var list = new List<Byte>();
for (int i = 0; i < binary.Length; i += 8)
{
String t = binary.Substring(i, 8);
list.Add(Convert.ToByte(t, 2));
}
return list.ToArray();
}
Once the binary string has been converted to a byte array, finish off with
Encoding.ASCII.GetString(data);
So...
var data = GetBytesFromBinaryString("010000010100001001000011");
var text = Encoding.ASCII.GetString(data);
If you have ASCII charters only you could use Encoding.ASCII.GetBytes and Encoding.ASCII.GetString.
var text = "Test";
var bytes = Encoding.ASCII.GetBytes(text);
var newText = Encoding.ASCII.GetString(bytes);
Here is complete code for your answer
FileStream iFile = new FileStream(#"c:\test\binary.dat",
FileMode.Open);
long lengthInBytes = iFile.Length;
BinaryReader bin = new BinaryReader(aFile);
byte[] byteArray = bin.ReadBytes((int)lengthInBytes);
System.Text.Encoding encEncoder = System.Text.ASCIIEncoding.ASCII;
string str = encEncoder.GetString(byteArray);
Take this as a simple example:
public void ByteToString()
{
Byte[] arrByte = { 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
string x = Convert.ToBase64String(arrByte);
}
This linked answer has interesting details about this kind of conversion:
binary file to string
Sometimes instead of using the built in tools it's better to use "custom" code.. try this function:
public string BinaryToString(string binary)
{
if (string.IsNullOrEmpty(binary))
throw new ArgumentNullException("binary");
if ((binary.Length % 8) != 0)
throw new ArgumentException("Binary string invalid (must divide by 8)", "binary");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < binary.Length; i += 8)
{
string section = binary.Substring(i, 8);
int ascii = 0;
try
{
ascii = Convert.ToInt32(section, 2);
}
catch
{
throw new ArgumentException("Binary string contains invalid section: " + section, "binary");
}
builder.Append((char)ascii);
}
return builder.ToString();
}
Tested with 010000010100001001000011 it returned ABC using the "raw" ASCII values.

Categories