Skip to content

Instantly share code, notes, and snippets.

@manuelfdo
Last active August 23, 2023 07:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manuelfdo/94a14c0314b07e311f07b240921eab86 to your computer and use it in GitHub Desktop.
Save manuelfdo/94a14c0314b07e311f07b240921eab86 to your computer and use it in GitHub Desktop.
Example of decoding Ecwid payment request using Web Cryptography API / SublteCrypto. https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
var bodyData = 'ECWID PAYLOAD';
var clientId = 'YOUR CLIENT SECRET';
// Added required padding to make the payload a multiple of 4. We can do this using a repeat or a simple while.
// var paddingLength = 4 - (bodyData.length % 4);
// if (paddingLength !== 4) {
// bodyData + '='.repeat(paddingLength);
// }
while (bodyData.length % 4 !== 0) {
bodyData += '=';
}
var originalBase64 = bodyData.replace(/-/g, "+").replace(/_/g, "/");
var decodedBase64 = atob(originalBase64);
var iv = str2ab(decodedBase64.substring(0, 16));
var cipherOrder = b642ab(originalBase64);
var keyData = str2ab(clientId.substring(0, 16));
async function decryptOrder() {
var key = await importKey();
try {
return await crypto.subtle.decrypt(
{ name: "AES-CBC", iv: iv },
key,
cipherOrder
);
} catch (exception) {
console.error(
"An error occurred, Name: ",
exception.name,
", Message: ",
exception.message
);
}
}
async function importKey() {
var key = await crypto.subtle.importKey(
"raw",
keyData,
{ name: "AES-CBC" },
true,
["decrypt"]
);
return key;
}
// Concept from https://stackoverflow.com/a/11058858. Convert String to Array Buffer
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
// Concept from https://stackoverflow.com/a/21797381/9014097 Convert Base64 to Array Buffer.
function b642ab(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
(async () => {
var decrypted = await decryptOrder();
var decryptedStr = new TextDecoder().decode(decrypted);
console.log(decryptedStr.substring(16));
})();
@manuelfdo
Copy link
Author

@parasdaryanani Thats a good solution! I saw the problem with 15/16 bytes but haven't had time to check why it happens.

@manuelfdo
Copy link
Author

@parasdaryanani Hey! I’ve modified the gist to include the required padding to make the payload multiple of 4, that should solve the issue with 15/16 bytes.

@parasdaryanani
Copy link

@manuelfdo brilliant, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment