I was trying to replicate/copy the encryption of an android app which uses CryptoJS with sha256 encryption as having seen in the source code of the android app. fingerprinting the app, it was built with reactJS and TypeScript and apparently compiled with Babel compiler, which all I don't understand them thoroughly. the code encrypts a signature to communicate with the server, Here is a snippet of the code:
f = t.type + "&" + encodeURIComponent(t.url) + "&" + n + "&" + u + "&" + b +
"&LS8goCQy4O2w5xnPmEOp/PjtKe37+d9HxRthqug9VC0=",
Signature = hexToBase64((0, c.default)(f).toString());
in the snippet code Signature = hexToBase64((0, c.default)(f).toString());
the signature is calculated but unfortunately because of source code was uglified and minified, in my research I identified the code responsible to calculate the signature is as follows:
__d(function (g, r, i, a, m, e, d) {
var t,
n;
t = this,
n = function (t) {
return (function (n) {
var o = t,
s = o.lib,
c = s.WordArray,
f = s.Hasher,
h = o.algo,
u = [],
l = [];
!(function () {
function t(t) {
for (var o = n.sqrt(t), s = 2; s <= o; s++)
if (!(t % s))
return !1;
return !0
}
function o(t) {
return 4294967296 * (t - (0 | t)) | 0
}
for (var s = 2, c = 0; c < 64; )
t(s) && (c < 8 && (u[c] = o(n.pow(s, .5))), l[c] = o(n.pow(s, .3333333333333333)), c++), s++
})();
var _ = [],
v = h.SHA256 = f.extend({
_doReset: function () {
this._hash = new c.init(u.slice(0))
},
_doProcessBlock: function (t, n) {
for (var o = this._hash.words, s = o[0], c = o[1], f = o[2], h = o[3], u = o[4], v = o[5], p = o[6], H = o[7], y = 0; y < 64; y++) {
if (y < 16)
_[y] = 0 | t[n + y];
else {
var w = _[y - 15],
A = (w << 25 | w >>> 7) ^ (w << 14 | w >>> 18) ^ w >>> 3,
S = _[y - 2],
B = (S << 15 | S >>> 17) ^ (S << 13 | S >>> 19) ^ S >>> 10;
_[y] = A + _[y - 7] + B + _[y - 16]
}
var b = s & c ^ s & f ^ c & f,
x = (s << 30 | s >>> 2) ^ (s << 19 | s >>> 13) ^ (s << 10 | s >>> 22),
j = H + ((u << 26 | u >>> 6) ^ (u << 21 | u >>> 11) ^ (u << 7 | u >>> 25)) + (u & v ^ ~u & p) + l[y] + _[y];
H = p,
p = v,
v = u,
u = h + j | 0,
h = f,
f = c,
c = s,
s = j + (x + b) | 0
}
o[0] = o[0] + s | 0,
o[1] = o[1] + c | 0,
o[2] = o[2] + f | 0,
o[3] = o[3] + h | 0,
o[4] = o[4] + u | 0,
o[5] = o[5] + v | 0,
o[6] = o[6] + p | 0,
o[7] = o[7] + H | 0
},
_doFinalize: function () {
var t = this._data,
o = t.words,
s = 8 * this._nDataBytes,
c = 8 * t.sigBytes;
return o[c >>> 5] |= 128 << 24 - c % 32,
o[14 + (c + 64 >>> 9 << 4)] = n.floor(s / 4294967296),
o[15 + (c + 64 >>> 9 << 4)] = s,
t.sigBytes = 4 * o.length,
this._process(),
this._hash
},
clone: function () {
var t = f.clone.call(this);
return t._hash = this._hash.clone(),
t
}
});
o.SHA256 = f._createHelper(v),
o.HmacSHA256 = f._createHmacHelper(v)
})(Math),
t.SHA256
},
"object" == typeof e ? m.exports = e = n(r(d[0])) : "function" == typeof define && define.amd ? define(["./core"], n) : n(t.CryptoJS)
}, 725, [726]);
another method with same functionality but with some minor changes was also defined:
__d(function (g, r, i, a, m, e, d) {
var t,
n;
t = this,
n = function () {
var t = t || (function (t, n) {
var o = Object.create || (function () {
function t() {}
return function (n) {
var o;
return t.prototype = n,
o = new t,
t.prototype = null,
o
}
})(),
s = {},
c = s.lib = {},
u = c.Base = {
extend: function (t) {
var n = o(this);
return t && n.mixIn(t),
n.hasOwnProperty('init') && this.init !== n.init || (n.init = function () {
n.$super.init.apply(this, arguments)
}),
n.init.prototype = n,
n.$super = this,
n
},
create: function () {
var t = this.extend();
return t.init.apply(t, arguments),
t
},
init: function () {},
mixIn: function (t) {
for (var n in t)
t.hasOwnProperty(n) && (this[n] = t[n]);
t.hasOwnProperty('toString') && (this.toString = t.toString)
},
clone: function () {
return this.init.prototype.extend(this)
}
},
f = c.WordArray = u.extend({
init: function (t, n) {
t = this.words = t || [],
this.sigBytes = void 0 != n ? n : 4 * t.length
},
toString: function (t) {
return (t || p).stringify(this)
},
concat: function (t) {
var n = this.words,
o = t.words,
s = this.sigBytes,
c = t.sigBytes;
if (this.clamp(), s % 4)
for (var u = 0; u < c; u++) {
var f = o[u >>> 2] >>> 24 - u % 4 * 8 & 255;
n[s + u >>> 2] |= f << 24 - (s + u) % 4 * 8
}
else
for (u = 0; u < c; u += 4)
n[s + u >>> 2] = o[u >>> 2];
return this.sigBytes += c,
this
},
clamp: function () {
var n = this.words,
o = this.sigBytes;
n[o >>> 2] &= 4294967295 << 32 - o % 4 * 8,
n.length = t.ceil(o / 4)
},
clone: function () {
var t = u.clone.call(this);
return t.words = this.words.slice(0),
t
},
random: function (n) {
for (var o, s = [], c = function (n) {
n = n;
var o = 987654321,
s = 4294967295;
return function () {
var c = ((o = 36969 * (65535 & o) + (o >> 16) & s) << 16) + (n = 18e3 * (65535 & n) + (n >> 16) & s) & s;
return c /= 4294967296,
(c += .5) * (t.random() > .5 ? 1 : -1)
}
}, u = 0; u < n; u += 4) {
var h = c(4294967296 * (o || t.random()));
o = 987654071 * h(),
s.push(4294967296 * h() | 0)
}
return new f.init(s, n)
}
}),
h = s.enc = {},
p = h.Hex = {
stringify: function (t) {
for (var n = t.words, o = t.sigBytes, s = [], c = 0; c < o; c++) {
var u = n[c >>> 2] >>> 24 - c % 4 * 8 & 255;
s.push((u >>> 4).toString(16)),
s.push((15 & u).toString(16))
}
return s.join('')
},
parse: function (t) {
for (var n = t.length, o = [], s = 0; s < n; s += 2)
o[s >>> 3] |= parseInt(t.substr(s, 2), 16) << 24 - s % 8 * 4;
return new f.init(o, n / 2)
}
},
l = h.Latin1 = {
stringify: function (t) {
for (var n = t.words, o = t.sigBytes, s = [], c = 0; c < o; c++) {
var u = n[c >>> 2] >>> 24 - c % 4 * 8 & 255;
s.push(String.fromCharCode(u))
}
return s.join('')
},
parse: function (t) {
for (var n = t.length, o = [], s = 0; s < n; s++)
o[s >>> 2] |= (255 & t.charCodeAt(s)) << 24 - s % 4 * 8;
return new f.init(o, n)
}
},
y = h.Utf8 = {
stringify: function (t) {
try {
return decodeURIComponent(escape(l.stringify(t)))
} catch (t) {
throw new Error('Malformed UTF-8 data')
}
},
parse: function (t) {
return l.parse(unescape(encodeURIComponent(t)))
}
},
v = c.BufferedBlockAlgorithm = u.extend({
reset: function () {
this._data = new f.init,
this._nDataBytes = 0
},
_append: function (t) {
'string' == typeof t && (t = y.parse(t)),
this._data.concat(t),
this._nDataBytes += t.sigBytes
},
_process: function (n) {
var o = this._data,
s = o.words,
c = o.sigBytes,
u = this.blockSize,
h = c / (4 * u),
p = (h = n ? t.ceil(h) : t.max((0 | h) - this._minBufferSize, 0)) * u,
l = t.min(4 * p, c);
if (p) {
for (var y = 0; y < p; y += u)
this._doProcessBlock(s, y);
var v = s.splice(0, p);
o.sigBytes -= l
}
return new f.init(v, l)
},
clone: function () {
var t = u.clone.call(this);
return t._data = this._data.clone(),
t
},
_minBufferSize: 0
}),
w = (c.Hasher = v.extend({
cfg: u.extend(),
init: function (t) {
this.cfg = this.cfg.extend(t),
this.reset()
},
reset: function () {
v.reset.call(this),
this._doReset()
},
update: function (t) {
return this._append(t),
this._process(),
this
},
finalize: function (t) {
return t && this._append(t),
this._doFinalize()
},
blockSize: 16,
_createHelper: function (t) {
return function (n, o) {
return new t.init(o).finalize(n)
}
},
_createHmacHelper: function (t) {
return function (n, o) {
return new w.HMAC.init(t, o).finalize(n)
}
}
}), s.algo = {});
return s
})(Math);
return t
},
"object" == typeof e ? m.exports = e = n() : "function" == typeof define && define.amd ? define([], n) : t.CryptoJS = n()
}, 726, []);
I didn't really understand which one is responsible to reproduce a signature like this : aoRxyvXwpTMh5wzMSz3nGZkkHwo6spNL1cz6qwjvnBA=
additionally in my research I was able to produce a signature but the server always returns invalid signature:
app signature : aoRxyvXwpTMh5wzMSz3nGZkkHwo6spNL1cz6qwjvnBA=
signature produced : Xpw28zTUMeJE9x4ki73tTs55IxDQy5Y4d0p9kgQgfo8=
what am I missing from the above code snippet? can I change it into a pure javascript code?