protected byte[] KeyStretching(byte[] data, byte[] hash) { byte[] stretching = new byte[data.Length + hash.Length + Salt.Length]; data.CopyTo(stretching, 0); hash.CopyTo(stretching, data.Length); Salt.CopyTo(stretching, data.Length + hash.Length); return(stretching); }
public void TestSaltCopy() { Salt s = new Salt(); byte[] bytes = new byte[s.Length]; s.CopyTo(bytes, 0); Assert.AreEqual(s.ToArray(), bytes); Assert.AreEqual(s.GetHashCode(), Salt.FromBytes(bytes).GetHashCode()); Salt strcpy = Salt.FromString(s.ToString()); Assert.AreEqual(s.ToArray(), strcpy.ToArray()); Assert.AreEqual(s.ToString(), strcpy.ToString()); Assert.AreEqual(s.GetHashCode(), strcpy.GetHashCode()); }
private static TextReader DecodeWebSaveData(string encodedSaveData) { const string AntiCheatCode = "Fe12NAfA3R6z4k0z"; var antiCheatCodeIndex = encodedSaveData.IndexOf(AntiCheatCode, StringComparison.Ordinal); if (antiCheatCodeIndex == -1) { // Couldn't find anti-cheat return(null); } // Remove every other character, AKA "unsprinkle". // Handle odd lengthed strings even though it shouldn't happen. var unsprinkledChars = new char[(antiCheatCodeIndex / 2) + (antiCheatCodeIndex % 2)]; for (var i = 0; i < antiCheatCodeIndex; i += 2) { unsprinkledChars[i / 2] = encodedSaveData[i]; } // Validation const string Salt = "af0ik392jrmt0nsfdghy0"; var expectedHashStart = antiCheatCodeIndex + AntiCheatCode.Length; var saltedChars = new char[unsprinkledChars.Length + Salt.Length]; unsprinkledChars.CopyTo(saltedChars, 0); Salt.CopyTo(0, saltedChars, unsprinkledChars.Length, Salt.Length); using (MD5 md5 = MD5.Create()) { byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(saltedChars)); var actualHash = new StringBuilder(data.Length * 2); for (int i = 0; i < data.Length; i++) { var expectedHashPartIndex = expectedHashStart + (i * 2); var actualHashPart = data[i].ToString("x2"); if (actualHashPart[0] != encodedSaveData[expectedHashPartIndex] || actualHashPart[1] != encodedSaveData[expectedHashPartIndex + 1]) { // Hash didn't match return(null); } } } // Decode var bytes = Convert.FromBase64CharArray(unsprinkledChars, 0, unsprinkledChars.Length); // Wrap in a text reader return(new StreamReader(new MemoryStream(bytes))); }
protected override byte[] ComputeHash() { byte[] dataPlusSalt = new byte[Data.Length + Salt.Length]; Data.CopyTo(dataPlusSalt, 0); Salt.CopyTo(dataPlusSalt, Data.Length); byte[] hash = SHA512.Create().ComputeHash(dataPlusSalt); byte[] stretching = new byte[0]; for (uint i = Iterations; i > 1; i--) { stretching = KeyStretching(stretching, hash); hash = SHA512.Create().ComputeHash(stretching); } return(hash); }