5

I have an algorithm in C# running on server side which hashes a base64-encoded string.

byte[] salt = Convert.FromBase64String(serverSalt); // Step 1
SHA256Managed sha256 = new SHA256Managed(); // Step 2
byte[] hash = sha256.ComputeHash(salt); // Step 3
Echo("String b64: " + Convert.ToBase64String(hash)); // Step 4

The hash is then checked against a database list of hashes. I'd love to achieve the same with javascript, using the serverSalt as it is transmitted from C# through a websocket.

I know SHA-256 hashes different between C# and Javascript because C# and Javascript have different string encodings. But I know I can pad zeros in the byte array to make Javascript behave as C# (step 1 above is solved).

var newSalt  = getByteArrayFromCSharpString(salt); // Pad zeros where needed
function getByteArrayFromCSharpString(inString)
{
  var bytes = [];
  for (var i = 0; i < inString.length; ++i)
{
    bytes.push(inString.charCodeAt(i));
    bytes.push(0);
}
return bytes;
}

Could anyone provide some insight on which algorithms I could use to reproduce steps 2, 3 and 4?

PS: there are already questions and answers around but not a single code snippet.

Community
  • 1
  • 1
malber
  • 1,053
  • 4
  • 16
  • 24
  • "I know that a byte array from C# and Javascript will be different" That's not true when working with binary data/base64. The only difference is the default conversion between string and bytes. Just use UTF-8 or UTF-16 for both, don't pad with zeros. – CodesInChaos Dec 11 '12 at 13:06
  • "I know that a byte array from C# and Javascript will be different" was in my original question, which was edited seconds later :) You're quite quick! What I meant is that same string in C# and Javascript will produce different byte arrays. Once the byte array is the same in both (step1), the algorithms (step2) should produce the same hashed byte array (step3). Then, I can convert both to base64 (step4). I'd love some insight on steps 2-4, there are many suggestions around but no code to speak of. – malber Dec 11 '12 at 14:34
  • 1
    When using base64, the conversion from string to bytes is the same for both C# and Javascript. The difference you're talking about only applies to text, and even then it's broken. – CodesInChaos Dec 11 '12 at 14:43
  • Thanks CodesInChaos, I managed to sort it out and you are absolutely right about the b64 <-> bytes conversion: it is the same in C# and Javascript – malber Dec 13 '12 at 10:41
  • "This is very suitable for secure client-server communication of hashed credentials" communication of hashed credentials is usually a bad approach that doesn't improve security over plaintext communication, and sometimes even decreases it. But without details I can't tell you much, only that no such scheme can replace SSL for webapplications. **Use SSL**. – CodesInChaos Dec 13 '12 at 10:56
  • Agreed, I'll edit my answer. – malber Dec 13 '12 at 14:27

2 Answers2

7

Here's the solution, I really hope this could help other people in the same situation.

In the html file, load crypto-js library

<!-- library for doing password hashing, base64 eoncoding / decoding -->
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/core-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/enc-base64-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/sha256.js"></script>

In the javascript, do the following

// This function takes a base64 string, hashes it with the SHA256 algorithm
// and returns a base64 string. 
function hashBase64StringAndReturnBase64String(str)
{
    // Take the base64 string and parse it into a javascript variable
    var words  = CryptoJS.enc.Base64.parse(str);
    // Create the hash using the CryptoJS implementation of the SHA256 algorithm
    var hash = CryptoJS.SHA256(words);
    var outString =  hash.toString(CryptoJS.enc.Base64)
    // Display what you just got and return it
    console.log("Output string is: " + outString);
    return outString;
}
malber
  • 1,053
  • 4
  • 16
  • 24
0

check Java script SHA256 implementation on the following URL http://www.movable-type.co.uk/scripts/sha256.html

Saddam Abu Ghaida
  • 6,381
  • 2
  • 22
  • 29
  • Thank you Saddam. I already looked at that URL and I get the same result as using CryptoJS, i.e. var hash = CryptoJS.SHA256(stringToHash); console.log("b64 " + hash.toString(CryptoJS.enc.Base64)); The resulting string, however, does not match the one obtained with C#. My fear is that both algorithms rely on an input string: given that I need to pad zeros to the byte array obtained with the original string, I'd rather work with bytes. – malber Dec 11 '12 at 14:08