-
-
Save hanchiang/ae411d08cb238ccefa0aef4b2c2899e0 to your computer and use it in GitHub Desktop.
Reverse engineering cryptopanic.com API response
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('dotenv').config(); | |
const CryptoJS = require("crypto-js"); | |
const pako = require('pako'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const ENCRYPTION_KEY = process.env.CRYPTOPANIC_ENCRYPTION_KEY; | |
const CSRF_TOKEN = process.env.CRYPTOPANIC_CSRF_TOKEN; | |
function wordToByteArray(t, e) { | |
var n = []; | |
return ( | |
e > 0 && n.push(t >>> 24), | |
e > 1 && n.push((t >>> 16) & 255), | |
e > 2 && n.push((t >>> 8) & 255), | |
e > 3 && n.push(255 & t), | |
n | |
); | |
} | |
function wordArrayToByteArray(t, e) { | |
t.hasOwnProperty("sigBytes") && | |
t.hasOwnProperty("words") && | |
((e = t.sigBytes), (t = t.words)); | |
for (var n, s = [], i = 0; e > 0; ) | |
(n = wordToByteArray(t[i], Math.min(4, e))), | |
(e -= n.length), | |
s.push(n), | |
i++; | |
return [].concat.apply([], s); | |
} | |
function normalizeDictList(t) { | |
var e = []; | |
return ( | |
t.l.forEach(function (n) { | |
var s = {}; | |
t.k.forEach(function (t, e) { | |
s[t] = n[e]; | |
}), | |
e.push(s); | |
}), | |
e | |
); | |
} | |
// { words, sigBytes } | |
const key = CryptoJS.enc.Utf8.parse(ENCRYPTION_KEY); | |
// for posts | |
const postIvRaw = "news" + CSRF_TOKEN.substring(0, 12); | |
// for dashboard | |
const dashboardIvRaw = "newsrnlistrnlist"; | |
const padding = CryptoJS.pad.ZeroPadding; | |
const postEncrypted = fs.readFileSync(path.join(__dirname, 'input', 'cryptopanic post data'), { encoding: 'utf-8' } ); | |
const dashboardEncrypted = fs.readFileSync(path.join(__dirname, 'input', 'cryptopanic dashboard data'), { encoding: 'utf-8' }); | |
const dataTypeMapping = { | |
post: { | |
iv: CryptoJS.enc.Utf8.parse(postIvRaw), | |
encrypted: postEncrypted | |
}, | |
dashboard: { | |
iv: CryptoJS.enc.Utf8.parse(dashboardIvRaw), | |
encrypted: dashboardEncrypted | |
} | |
} | |
function decrypt(encrypted, key, iv, padding, dataType) { | |
// { words, sigBytes } | |
const decrypted = CryptoJS.AES.decrypt(encrypted, key, { | |
iv, | |
padding, | |
}); | |
const byteArray = wordArrayToByteArray(decrypted); | |
try { | |
const inflated = pako.inflate(byteArray, { to: 'string' }); | |
const inflatedJson = JSON.parse(inflated); | |
fs.writeFileSync(path.join(__dirname, 'decrypted', `${dataType}-inflatedRaw.json`), JSON.stringify(inflatedJson, undefined, 2)); | |
const normalized = normalizeDictList(inflatedJson); | |
fs.writeFileSync(path.join(__dirname, 'decrypted', `${dataType}-normalized.json`), JSON.stringify(normalized, undefined, 2)); | |
return normalized; | |
} catch(e) { | |
console.log(e); | |
} | |
} | |
// node decrypt.js | |
// dataType = 'post', 'dashboard' | |
if (require.main === module) { | |
let [_, __, dataType] = process.argv; | |
dataType = dataType ? dataType : 'post'; | |
const decrypted = decrypt(dataTypeMapping[dataType].encrypted, key, dataTypeMapping[dataType].iv, padding, dataType); | |
console.log(decrypted); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment