As a contemporary alternative, there is a standard now for client side cryptography. This has the advantage of being optimised by the browser itself.
Taken from the example in the documentation:
async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder('utf-8').encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
return hashHex;
}
sha256('abc').then(hash => console.log(hash));
(async function() {
const hash = await sha256('abc');
}());
MD5 is likely unsupported, however the likes of SHA-256, SHA-384, and SHA-512 are.
And those will likely be able to be calculated server side also.
Here's some documentation on usage: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
And cross browser compatibility: https://caniuse.com/#feat=cryptography