I am developing a website that has an upload feature.
In the frontend the I used Javascript library CryptoJS to calculate the SHA-256 hash from the file content and send it along with the file to the server.
function onMyfileChange(fileInput) {
if(fileInput.files[0] == undefined) {
return ;
}
var filename = fileInput.files[0].name;
var reader = new FileReader();
reader.onload = function(ev) {
var fileContent = ev.target.result;
var sha256hash = CryptoJS.SHA256(fileContent).toString(CryptoJS.enc.Hex);
// do something with the hash
};
reader.onerror = function(err) {
console.error("Failed to read file", err);
}
reader.readAsArrayBuffer(fileInput.files[0]);
}
In the backend server I use Java to calculate the SHA-256 hash from the file content again and compare it with the SHA-256 hash sent from the server to check the integrity of the file.
import org.apache.commons.codec.digest.DigestUtils;
byte[] data = ...
String sha256hash = DigestUtils.sha256Hex(data);
The problem is the SHA-256 hash calculated by CryptoJS is different than the one calculated by Java.
To crosscheck I use an online tool to verify the SHA-256 hash from the same file.
I also developed a tool written in C# to calculate the SHA-256 hash.
var fileContent = File.ReadAllBytes(fileName);
var sha = SHA256.Create();
byte[] checksum = sha.ComputeHash(fileContent);
var sha256 = BitConverter.ToString(checksum).Replace("-", String.Empty);
Console.WriteLine(sha256.ToString());
The SHA-256 hash calculated by Java is the same as the one generated by the online tool and the C# tool I wrote so there must be something wrong with the way I am using CryptoJS.
Instead of passing the array buffer to the CryptoJS.SHA256 I need to convert it to WordArray first.
var fileContent = ev.target.result;
var wa = CryptoJS.lib.WordArray.create(fileContent);
var sha256hash = CryptoJS.SHA256(wa).toString(CryptoJS.enc.Hex);