Decompression Routine In Javascript to Python - javascript

I'm trying to rewrite a javascript file decompression routine to python. But I can't seem to get it right. The function always returns None on python.
Here is the original JS:
var c = new Uint8Array(b),
d = 0,
e = new Uint32Array(4096),
f = new Uint32Array(4096),
g = 256,
h = a.length,
k = 0,
l = 1,
m = 0,
n = 1;
c[d++] = a[0];
for (var r = 1;; r++) {
n = r + (r >> 1);
if (n + 1 >= h) break;
var m = a[n + 1],
n = a[n],
p = r & 1 ? m << 4 | n >> 4 : (m & 15) << 8 | n;
if (p < g)
if (256 > p) m = d, n = 1, c[d++] = p;
else
for (var m = d, n = f[p], p = e[p], q = p + n; p < q;) c[d++] = c[p++];
else if (p == g) {
m = d;
n = l + 1;
p = k;
for (q = k + l; p < q;) c[d++] = c[p++];
c[d++] = c[k]
} else break;
e[g] = k;
f[g++] = l + 1;
k = m;
l = n;
g = 4096 <= g ? 256 : g
}
return d == b ? c : null
And here is my python implementation, what did I do wrong? (Improved with #le_m answer but still returning None.)
c = [0] * b
d = 0
e = [0] * 4096
f = [0] * 4096
g = 256
h = len(a)
k = 0
l = 1
m = 0
n = 1
c[d] = a[0]
d += 1
r = 1
while True:
n = r + (r >> 1)
if (n + 1) >= h:
break
m = a[n + 1]
n = a[n]
p = (m << 4 | n >> 4) if r & 1 else ((m & 15) << 8 | n)
if (p < g):
if (256 > p):
m = d
n = 1
c[d] = p
d += 1
else:
m = d
n = f[p]
p = e[p]
q = p + n
while p < q:
c[d] = c[p]
d += 1
p += 1
elif p == g:
m = d
n = 1 + 1
p = k
q = k + l
while p < q:
c[d] = c[p]
d += 1
p += 1
else:
break
e[g] = k
f[g] = l + 1
g += 1
k = m
l = n
g = 256 if 4096 <= g else g
r += 1

Just from glancing at the code, I spot the following differences:
new Uint8Array(b) translates to [0] * b as the typed array is initialized with zeros. Same holds for the other typed arrays.
c[d++] = a[0] translates to c[d] = a[0] followed by d += 1, not the other way round. Same holds for the other post-increments, too.
The loop counter r += 1 should go to the end of the loop body or should be initialized with 0 instead.
I recommend stepping through both implementations step by step with a debugger (your browser's developer console for JavaScript) and compare the variable values.

Related

Submitting an OTP to Microsoft API with RSA encryption

I'm gonna keep this short and clean.
I need to submit an OTP to Microsoft's API. This OTP however, is encrypted on the client side with some JavaScript function and then submitted to the API. That's the Microsoft's script for encryption (the original script has over 2000 lines, I only left functions used by Encrypt() function. I believe it is just plain RSA encryption in JavaScript but I could be wrong):
function Encrypt(e, t, i, r) {
var n = [];
switch (i.toLowerCase()) {
case "saproof":
if (null == t) {
return null
}
n = PackageSADataForProof(t);
break;
case "newpwd":
if (null == r) {
return null
}
}
if (null == n || "undefined" == typeof n) {
return n
}
if ("undefined" != typeof Key && void 0 !== parseRSAKeyFromString) {
var o = parseRSAKeyFromString(Key)
}
var s = RSAEncrypt(n, o, randomNum);
return s
}
function PackageSADataForProof(e) {
var t, i = [], r = 0;
for (t = 0; t < e.length; t++) {
i[r++] = 127 & e.charCodeAt(t),
i[r++] = (65280 & e.charCodeAt(t)) >> 8
}
return i
}
function parseRSAKeyFromString(e) {
var t = e.indexOf(";");
if (0 > t) {
return null
}
var i = e.substr(0, t)
, r = e.substr(t + 1)
, n = i.indexOf("=");
if (0 > n) {
return null
}
var o = i.substr(n + 1);
if (n = r.indexOf("="),
0 > n) {
return null
}
var s = r.substr(n + 1)
, a = new Object;
return a.n = hexStringToMP(s),
a.e = parseInt(o, 16),
a
}
function hexStringToMP(e) {
var t, i, r = Math.ceil(e.length / 4), n = new JSMPnumber;
for (n.size = r,
t = 0; r > t; t++) {
i = e.substr(4 * t, 4),
n.data[r - 1 - t] = parseInt(i, 16)
}
return n
}
function RSAEncrypt(e, t) {
for (var i = [], r = 42, n = 2 * t.n.size - r, o = 0; o < e.length; o += n) {
if (o + n >= e.length) {
var s = RSAEncryptBlock(e.slice(o), t, randomNum);
s && (i = s.concat(i))
} else {
var s = RSAEncryptBlock(e.slice(o, o + n), t, randomNum);
s && (i = s.concat(i))
}
}
var a = byteArrayToBase64(i);
return a
}
function RSAEncryptBlock(e, t, i) {
var r = t.n
, n = t.e
, o = e.length
, s = 2 * r.size
, a = 42;
if (o + a > s) {
return null
}
applyPKCSv2Padding(e, s, i),
e = e.reverse();
var l = byteArrayToMP(e)
, d = modularExp(l, n, r);
d.size = r.size;
var h = mpToByteArray(d);
return h = h.reverse()
}
function JSMPnumber() {
this.size = 1,
this.data = [],
this.data[0] = 0
}
function byteArrayToMP(e) {
var t = new JSMPnumber
, i = 0
, r = e.length
, n = r >> 1;
for (i = 0; n > i; i++) {
t.data[i] = e[2 * i] + (e[1 + 2 * i] << 8)
}
return r % 2 && (t.data[i++] = e[r - 1]),
t.size = i,
t
}
function modularExp(e, t, i) {
for (var r = [], n = 0; t > 0; ) {
r[n] = 1 & t,
t >>>= 1,
n++
}
for (var o = duplicateMP(e), s = n - 2; s >= 0; s--) {
o = modularMultiply(o, o, i),
1 == r[s] && (o = modularMultiply(o, e, i))
}
return o
}
function modularMultiply(e, t, i) {
var r = multiplyMP(e, t)
, n = divideMP(r, i);
return n.r
}
function multiplyMP(e, t) {
var i = new JSMPnumber;
i.size = e.size + t.size;
var r, n;
for (r = 0; r < i.size; r++) {
i.data[r] = 0
}
var o = e.data
, s = t.data
, a = i.data;
if (e == t) {
for (r = 0; r < e.size; r++) {
a[2 * r] += o[r] * o[r]
}
for (r = 1; r < e.size; r++) {
for (n = 0; r > n; n++) {
a[r + n] += 2 * o[r] * o[n]
}
}
} else {
for (r = 0; r < e.size; r++) {
for (n = 0; n < t.size; n++) {
a[r + n] += o[r] * s[n]
}
}
}
return normalizeJSMP(i),
i
}
function normalizeJSMP(e) {
var t, i, r, n, o;
for (r = e.size,
i = 0,
t = 0; r > t; t++) {
n = e.data[t],
n += i,
o = n,
i = Math.floor(n / 65536),
n -= 65536 * i,
e.data[t] = n
}
}
function removeLeadingZeroes(e) {
for (var t = e.size - 1; t > 0 && 0 == e.data[t--]; ) {
e.size--
}
}
function divideMP(e, t) {
var i = e.size
, r = t.size
, n = t.data[r - 1]
, o = t.data[r - 1] + t.data[r - 2] / 65536
, s = new JSMPnumber;
s.size = i - r + 1,
e.data[i] = 0;
for (var a = i - 1; a >= r - 1; a--) {
var l = a - r + 1
, d = Math.floor((65536 * e.data[a + 1] + e.data[a]) / o);
if (d > 0) {
var h = multiplyAndSubtract(e, d, t, l);
for (0 > h && (d--,
multiplyAndSubtract(e, d, t, l)); h > 0 && e.data[a] >= n; ) {
h = multiplyAndSubtract(e, 1, t, l),
h > 0 && d++
}
}
s.data[l] = d
}
removeLeadingZeroes(e);
var u = {
"q": s,
"r": e
};
return u
}
function multiplyAndSubtract(e, t, i, r) {
var n, o = e.data.slice(0), s = 0, a = e.data;
for (n = 0; n < i.size; n++) {
var l = s + i.data[n] * t;
s = l >>> 16,
l -= 65536 * s,
l > a[n + r] ? (a[n + r] += 65536 - l,
s++) : a[n + r] -= l
}
return s > 0 && (a[n + r] -= s),
a[n + r] < 0 ? (e.data = o.slice(0),
-1) : 1
}
function applyPKCSv2Padding(e, t, i) {
var r, n = e.length, o = [218, 57, 163, 238, 94, 107, 75, 13, 50, 85, 191, 239, 149, 96, 24, 144, 175, 216, 7, 9], s = t - n - 40 - 2, a = [];
for (r = 0; s > r; r++) {
a[r] = 0
}
a[s] = 1;
var l = o.concat(a, e)
, d = [];
for (r = 0; 20 > r; r++) {
d[r] = Math.floor(256 * Math.random())
}
d = SHA1(d.concat(i));
var h = MGF(d, t - 21)
, u = XORarrays(l, h)
, c = MGF(u, 20)
, p = XORarrays(d, c)
, f = [];
for (f[0] = 0,
f = f.concat(p, u),
r = 0; r < f.length; r++) {
e[r] = f[r]
}
}
function MGF(e, t) {
if (t > 4096) {
return null
}
var i = e.slice(0)
, r = i.length;
i[r++] = 0,
i[r++] = 0,
i[r++] = 0,
i[r] = 0;
for (var n = 0, o = []; o.length < t; ) {
i[r] = n++,
o = o.concat(SHA1(i))
}
return o.slice(0, t)
}
function XORarrays(e, t) {
if (e.length != t.length) {
return null
}
for (var i = [], r = e.length, n = 0; r > n; n++) {
i[n] = e[n] ^ t[n]
}
return i
}
function SHA1(e) {
var t, i = e.slice(0);
PadSHA1Input(i);
var r = {
"A": 1732584193,
"B": 4023233417,
"C": 2562383102,
"D": 271733878,
"E": 3285377520
};
for (t = 0; t < i.length; t += 64) {
SHA1RoundFunction(r, i, t)
}
var n = [];
return wordToBytes(r.A, n, 0),
wordToBytes(r.B, n, 4),
wordToBytes(r.C, n, 8),
wordToBytes(r.D, n, 12),
wordToBytes(r.E, n, 16),
n
}
function wordToBytes(e, t, i) {
var r;
for (r = 3; r >= 0; r--) {
t[i + r] = 255 & e,
e >>>= 8
}
}
function PadSHA1Input(e) {
var t, i = e.length, r = i, n = i % 64, o = 55 > n ? 56 : 120;
for (e[r++] = 128,
t = n + 1; o > t; t++) {
e[r++] = 0
}
var s = 8 * i;
for (t = 1; 8 > t; t++) {
e[r + 8 - t] = 255 & s,
s >>>= 8
}
}
function SHA1RoundFunction(e, t, i) {
var r, n, o, s = 1518500249, a = 1859775393, l = 2400959708, d = 3395469782, h = [], u = e.A, c = e.B, p = e.C, f = e.D, m = e.E;
for (n = 0,
o = i; 16 > n; n++,
o += 4) {
h[n] = t[o] << 24 | t[o + 1] << 16 | t[o + 2] << 8 | t[o + 3] << 0
}
for (n = 16; 80 > n; n++) {
h[n] = rotateLeft(h[n - 3] ^ h[n - 8] ^ h[n - 14] ^ h[n - 16], 1)
}
var g;
for (r = 0; 20 > r; r++) {
g = rotateLeft(u, 5) + (c & p | ~c & f) + m + h[r] + s & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 20; 40 > r; r++) {
g = rotateLeft(u, 5) + (c ^ p ^ f) + m + h[r] + a & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 40; 60 > r; r++) {
g = rotateLeft(u, 5) + (c & p | c & f | p & f) + m + h[r] + l & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 60; 80 > r; r++) {
g = rotateLeft(u, 5) + (c ^ p ^ f) + m + h[r] + d & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
e.A = e.A + u & 4294967295,
e.B = e.B + c & 4294967295,
e.C = e.C + p & 4294967295,
e.D = e.D + f & 4294967295,
e.E = e.E + m & 4294967295
}
function rotateLeft(e, t) {
var i = e >>> 32 - t
, r = (1 << 32 - t) - 1
, n = e & r;
return n << t | i
}
function hexStringToMP(e) {
var t, i, r = Math.ceil(e.length / 4), n = new JSMPnumber;
for (n.size = r,
t = 0; r > t; t++) {
i = e.substr(4 * t, 4),
n.data[r - 1 - t] = parseInt(i, 16)
}
return n
}
function duplicateMP(e) {
var t = new JSMPnumber;
return t.size = e.size,
t.data = e.data.slice(0),
t
}
function mpToByteArray(e) {
var t = []
, i = 0
, r = e.size;
for (i = 0; r > i; i++) {
t[2 * i] = 255 & e.data[i];
var n = e.data[i] >>> 8;
t[2 * i + 1] = n
}
return t
}
function byteArrayToBase64(e) {
var t, i, r = e.length, n = "";
for (t = r - 3; t >= 0; t -= 3) {
i = e[t] | e[t + 1] << 8 | e[t + 2] << 16,
n += base64Encode(i, 4)
}
var o = r % 3;
for (i = 0,
t += 2; t >= 0; t--) {
i = i << 8 | e[t]
}
return 1 == o ? n = n + base64Encode(i << 16, 2) + "==" : 2 == o && (n = n + base64Encode(i << 8, 3) + "="),
n
}
function base64Encode(e, t) {
var i, r = "";
for (i = t; 4 > i; i++) {
e >>= 6
}
for (i = 0; t > i; i++) {
r = mapByteToBase64(63 & e) + r,
e >>= 6
}
return r
}
function mapByteToBase64(e) {
return e >= 0 && 26 > e ? String.fromCharCode(65 + e) : e >= 26 && 52 > e ? String.fromCharCode(97 + e - 26) : e >= 52 && 62 > e ? String.fromCharCode(48 + e - 52) : 62 == e ? "+" : "/"
}
var Key = "e=10001;m=d0fa1d37fa0bb621a8cbb6669249ba1d14bbd5058592f050240d8c3b68674f0e28283018a7753f4377aaa3b3645e5f119a0032129a0a64322f74888aed3519de49e98c5b3c221460218140616f01ac5e9f2f8042e2749b8a89112f15310690dad7531f6758c0c65e525dff7859283b566a5b154352c57161cd24e59133a61432f461583e40cac749d722909dfcf0edd6af3cbc9a25e639b0caaf55e8c7b08b53c7d52038b48e1b26ad40f8bb84b3bb9c92bc9b947d2ab5ae4664a5093a4895af09659a78c9393797ea76b5b9416a45025e2ab3ea1627f08d85abd22e156d3e842efbaa1d0e1e4885028b2bc0aa7be8e444799e96fce0444f2b56bd14c0244b4d"
var randomNum = "AA278C7C00D44877AA95055BB0497A6169195B7B79C664E0AC9DFDCE1112CE28282BAA83D5CD95041CB512CD35624CCD6FD873C98579E4D3C4D25E5E6134F65628BDA9DE9C00A6E53A0194EA7483BCB1AABD8AA983282259E2953CC8705D36BB9936E57E"
console.log(Encrypt(null, "1234", "saproof"))
Example output from above code
V2loAc3ik+qXTJMVF/V/0yKdbQeKGqO7UIA82cqafWUPJ6ALYd/6Bwb9QFsJOEC+yKfwqu5YE36+J3Dpsuk14EQG4YktFVao5D2i5C/2Akm5i1WhPDMbHUFfUJtxbQ3Ldc0jgpMpOrhuEkQ/u9MUgL3l1tL08GTvl4KdnvW2delt1HpuyGFI11WNb5/xXbzmZvRsF2fc3tNpZCvHSTCEQuMOzsQSTeghttXEBFFvmqC9fwH+KjiBGwl11zyH+shv8kYi+LRaqN2LoVz4eFMmWDJ0PNNeA7Aq+mQ/9BIY+tz7Tzz51OSlCgajsPnJbxyHiURdUrc103oKdja8Vd9dnw==
The main function here is Encrypt(). My program is written in Python. I tried encrypting my OTP using Python's rsa module but to no avail. The API rejected the request and marked the encrypted OTP as invalid.
import rsa
import base64
Key = "d0fa1d37fa0bb621a8cbb6669249ba1d14bbd5058592f050240d8c3b68674f0e28283018a7753f4377aaa3b3645e5f119a0032129a0a64322f74888aed3519de49e98c5b3c221460218140616f01ac5e9f2f8042e2749b8a89112f15310690dad7531f6758c0c65e525dff7859283b566a5b154352c57161cd24e59133a61432f461583e40cac749d722909dfcf0edd6af3cbc9a25e639b0caaf55e8c7b08b53c7d52038b48e1b26ad40f8bb84b3bb9c92bc9b947d2ab5ae4664a5093a4895af09659a78c9393797ea76b5b9416a45025e2ab3ea1627f08d85abd22e156d3e842efbaa1d0e1e4885028b2bc0aa7be8e444799e96fce0444f2b56bd14c0244b4d"
encrypted = rsa.encrypt(b'1234', rsa.PublicKey(int(Key, 16), 65537))
b64encrypted = base64.b64encode(encrypted)
print(b64encrypted.decode('utf-8'))
So my question is, how can I use Microsoft's encryption function in Python? Do I need to manually translate the code myself, or maybe I am doing something wrong with rsa module?
Thanks for help.
The JavaScript code uses RSA with OAEP as padding and SHA-1 for both digests (see applyPKCSv2Padding()). In addition, the plaintext is encoded with UTF-16LE (see PackageSADataForProof()) and the ciphertext is encoded in little endian order (see byteArrayToBase64()).
The RSA library used does not support OAEP, see issue #68. A possible library that supports OAEP is PyCryptodome and a possible implementation that is functionally identical to the JavaScript code is (strictly speaking, this applies only to plaintexts up to 214 bytes, for longer ones see the next section):
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
modulusHex = 'd0fa1d37fa0bb621a8cbb6669249ba1d14bbd5058592f050240d8c3b68674f0e28283018a7753f4377aaa3b3645e5f119a0032129a0a64322f74888aed3519de49e98c5b3c221460218140616f01ac5e9f2f8042e2749b8a89112f15310690dad7531f6758c0c65e525dff7859283b566a5b154352c57161cd24e59133a61432f461583e40cac749d722909dfcf0edd6af3cbc9a25e639b0caaf55e8c7b08b53c7d52038b48e1b26ad40f8bb84b3bb9c92bc9b947d2ab5ae4664a5093a4895af09659a78c9393797ea76b5b9416a45025e2ab3ea1627f08d85abd22e156d3e842efbaa1d0e1e4885028b2bc0aa7be8e444799e96fce0444f2b56bd14c0244b4d';
pubExpHex = '010001'
plaintextStr = '1234'
modulus = int(modulusHex, 16)
pubExp = int(pubExpHex, 16)
plaintext = plaintextStr.encode('utf-16le') # encode plaintext with UTF-16LE
publicKey = RSA.construct((modulus, pubExp))
cipher = PKCS1_OAEP.new(publicKey) # apply OAEP as padding
ciphertext = cipher.encrypt(plaintext)
ciphertextReversed = ciphertext[::-1] # encode ciphertext in little endian order
ciphertextReversedB64 = base64.b64encode(ciphertextReversed)
print(ciphertextReversedB64)
Note that OAEP is not deterministic, i.e. repeated encryption with the same key and plaintext gives different ciphertexts. Therefore, the implementation cannot be verified by comparing the ciphertexts, but only by a successful decryption (see the last section).
Plaintexts, larger than 214 bytes: The posted JavaScript code implements a rather unusual feature: RSA can only encrypt plaintexts whose maximum length is equal to the key length (here 2048 bits = 256 bytes) minus the space required by the padding (here for OAEP with SHA-1: 42 bytes), i.e. the maximum length here is 256 - 42 = 214 bytes, see here.
But the Java Script code posted here splits the plaintext into blocks of 214 bytes (or less in the case of the last block), encrypts each block separately and concatenates the ciphertexts. This allows encryption of arbitrarily long plaintexts.
The Python code snippet above does not take this into account, since it is not needed for the short plaintext 1234 used in the example. But for plaintexts larger than 214 bytes this has to be added.
Note that usually long plaintexts are not encrypted this way, but with hybrid encryption, in which e.g. RSA is combined with AES: The plaintext is encrypted with AES, the AES key with RSA.
Test: The JavaScript code below decrypts a ciphertext generated with the JavaScript code posted in the question and a ciphertext generated with the Python code posted in this answer.
Result: Both ciphertexts can be decrypted with the same logic, which shows that the JavaScript and Python encryption code are functionally identical.
Note that a new key pair was used for this test, since only the public key was posted in the question, and that the public key of this new key pair must be applied when generating the ciphertexts (see JavaScript code for encryption) so that the private key used in decryption matches.
(async () => {
function Encrypt(e, t, i, r) {
var n = [];
switch (i.toLowerCase()) {
case "saproof":
if (null == t) {
return null
}
n = PackageSADataForProof(t);
break;
case "newpwd":
if (null == r) {
return null
}
}
if (null == n || "undefined" == typeof n) {
return n
}
if ("undefined" != typeof Key && void 0 !== parseRSAKeyFromString) {
var o = parseRSAKeyFromString(Key)
}
var s = RSAEncrypt(n, o, randomNum);
return s
}
function PackageSADataForProof(e) {
var t, i = [], r = 0;
for (t = 0; t < e.length; t++) {
i[r++] = 127 & e.charCodeAt(t),
i[r++] = (65280 & e.charCodeAt(t)) >> 8
}
return i
}
function parseRSAKeyFromString(e) {
var t = e.indexOf(";");
if (0 > t) {
return null
}
var i = e.substr(0, t)
, r = e.substr(t + 1)
, n = i.indexOf("=");
if (0 > n) {
return null
}
var o = i.substr(n + 1);
if (n = r.indexOf("="),
0 > n) {
return null
}
var s = r.substr(n + 1)
, a = new Object;
return a.n = hexStringToMP(s),
a.e = parseInt(o, 16),
a
}
function hexStringToMP(e) {
var t, i, r = Math.ceil(e.length / 4), n = new JSMPnumber;
for (n.size = r,
t = 0; r > t; t++) {
i = e.substr(4 * t, 4),
n.data[r - 1 - t] = parseInt(i, 16)
}
return n
}
function RSAEncrypt(e, t) {
for (var i = [], r = 42, n = 2 * t.n.size - r, o = 0; o < e.length; o += n) {
if (o + n >= e.length) {
var s = RSAEncryptBlock(e.slice(o), t, randomNum);
s && (i = s.concat(i))
} else {
var s = RSAEncryptBlock(e.slice(o, o + n), t, randomNum);
s && (i = s.concat(i))
}
}
var a = byteArrayToBase64(i);
return a
}
function RSAEncryptBlock(e, t, i) {
var r = t.n
, n = t.e
, o = e.length
, s = 2 * r.size
, a = 42;
if (o + a > s) {
return null
}
applyPKCSv2Padding(e, s, i),
e = e.reverse();
var l = byteArrayToMP(e)
, d = modularExp(l, n, r);
d.size = r.size;
var h = mpToByteArray(d);
return h = h.reverse()
}
function JSMPnumber() {
this.size = 1,
this.data = [],
this.data[0] = 0
}
function byteArrayToMP(e) {
var t = new JSMPnumber
, i = 0
, r = e.length
, n = r >> 1;
for (i = 0; n > i; i++) {
t.data[i] = e[2 * i] + (e[1 + 2 * i] << 8)
}
return r % 2 && (t.data[i++] = e[r - 1]),
t.size = i,
t
}
function modularExp(e, t, i) {
for (var r = [], n = 0; t > 0; ) {
r[n] = 1 & t,
t >>>= 1,
n++
}
for (var o = duplicateMP(e), s = n - 2; s >= 0; s--) {
o = modularMultiply(o, o, i),
1 == r[s] && (o = modularMultiply(o, e, i))
}
return o
}
function modularMultiply(e, t, i) {
var r = multiplyMP(e, t)
, n = divideMP(r, i);
return n.r
}
function multiplyMP(e, t) {
var i = new JSMPnumber;
i.size = e.size + t.size;
var r, n;
for (r = 0; r < i.size; r++) {
i.data[r] = 0
}
var o = e.data
, s = t.data
, a = i.data;
if (e == t) {
for (r = 0; r < e.size; r++) {
a[2 * r] += o[r] * o[r]
}
for (r = 1; r < e.size; r++) {
for (n = 0; r > n; n++) {
a[r + n] += 2 * o[r] * o[n]
}
}
} else {
for (r = 0; r < e.size; r++) {
for (n = 0; n < t.size; n++) {
a[r + n] += o[r] * s[n]
}
}
}
return normalizeJSMP(i),
i
}
function normalizeJSMP(e) {
var t, i, r, n, o;
for (r = e.size,
i = 0,
t = 0; r > t; t++) {
n = e.data[t],
n += i,
o = n,
i = Math.floor(n / 65536),
n -= 65536 * i,
e.data[t] = n
}
}
function removeLeadingZeroes(e) {
for (var t = e.size - 1; t > 0 && 0 == e.data[t--]; ) {
e.size--
}
}
function divideMP(e, t) {
var i = e.size
, r = t.size
, n = t.data[r - 1]
, o = t.data[r - 1] + t.data[r - 2] / 65536
, s = new JSMPnumber;
s.size = i - r + 1,
e.data[i] = 0;
for (var a = i - 1; a >= r - 1; a--) {
var l = a - r + 1
, d = Math.floor((65536 * e.data[a + 1] + e.data[a]) / o);
if (d > 0) {
var h = multiplyAndSubtract(e, d, t, l);
for (0 > h && (d--,
multiplyAndSubtract(e, d, t, l)); h > 0 && e.data[a] >= n; ) {
h = multiplyAndSubtract(e, 1, t, l),
h > 0 && d++
}
}
s.data[l] = d
}
removeLeadingZeroes(e);
var u = {
"q": s,
"r": e
};
return u
}
function multiplyAndSubtract(e, t, i, r) {
var n, o = e.data.slice(0), s = 0, a = e.data;
for (n = 0; n < i.size; n++) {
var l = s + i.data[n] * t;
s = l >>> 16,
l -= 65536 * s,
l > a[n + r] ? (a[n + r] += 65536 - l,
s++) : a[n + r] -= l
}
return s > 0 && (a[n + r] -= s),
a[n + r] < 0 ? (e.data = o.slice(0),
-1) : 1
}
function applyPKCSv2Padding(e, t, i) {
var r, n = e.length, o = [218, 57, 163, 238, 94, 107, 75, 13, 50, 85, 191, 239, 149, 96, 24, 144, 175, 216, 7, 9], s = t - n - 40 - 2, a = [];
for (r = 0; s > r; r++) {
a[r] = 0
}
a[s] = 1;
var l = o.concat(a, e)
, d = [];
for (r = 0; 20 > r; r++) {
d[r] = Math.floor(256 * Math.random())
}
d = SHA1(d.concat(i));
var h = MGF(d, t - 21)
, u = XORarrays(l, h)
, c = MGF(u, 20)
, p = XORarrays(d, c)
, f = [];
for (f[0] = 0,
f = f.concat(p, u),
r = 0; r < f.length; r++) {
e[r] = f[r]
}
}
function MGF(e, t) {
if (t > 4096) {
return null
}
var i = e.slice(0)
, r = i.length;
i[r++] = 0,
i[r++] = 0,
i[r++] = 0,
i[r] = 0;
for (var n = 0, o = []; o.length < t; ) {
i[r] = n++,
o = o.concat(SHA1(i))
}
return o.slice(0, t)
}
function XORarrays(e, t) {
if (e.length != t.length) {
return null
}
for (var i = [], r = e.length, n = 0; r > n; n++) {
i[n] = e[n] ^ t[n]
}
return i
}
function SHA1(e) {
var t, i = e.slice(0);
PadSHA1Input(i);
var r = {
"A": 1732584193,
"B": 4023233417,
"C": 2562383102,
"D": 271733878,
"E": 3285377520
};
for (t = 0; t < i.length; t += 64) {
SHA1RoundFunction(r, i, t)
}
var n = [];
return wordToBytes(r.A, n, 0),
wordToBytes(r.B, n, 4),
wordToBytes(r.C, n, 8),
wordToBytes(r.D, n, 12),
wordToBytes(r.E, n, 16),
n
}
function wordToBytes(e, t, i) {
var r;
for (r = 3; r >= 0; r--) {
t[i + r] = 255 & e,
e >>>= 8
}
}
function PadSHA1Input(e) {
var t, i = e.length, r = i, n = i % 64, o = 55 > n ? 56 : 120;
for (e[r++] = 128,
t = n + 1; o > t; t++) {
e[r++] = 0
}
var s = 8 * i;
for (t = 1; 8 > t; t++) {
e[r + 8 - t] = 255 & s,
s >>>= 8
}
}
function SHA1RoundFunction(e, t, i) {
var r, n, o, s = 1518500249, a = 1859775393, l = 2400959708, d = 3395469782, h = [], u = e.A, c = e.B, p = e.C, f = e.D, m = e.E;
for (n = 0,
o = i; 16 > n; n++,
o += 4) {
h[n] = t[o] << 24 | t[o + 1] << 16 | t[o + 2] << 8 | t[o + 3] << 0
}
for (n = 16; 80 > n; n++) {
h[n] = rotateLeft(h[n - 3] ^ h[n - 8] ^ h[n - 14] ^ h[n - 16], 1)
}
var g;
for (r = 0; 20 > r; r++) {
g = rotateLeft(u, 5) + (c & p | ~c & f) + m + h[r] + s & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 20; 40 > r; r++) {
g = rotateLeft(u, 5) + (c ^ p ^ f) + m + h[r] + a & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 40; 60 > r; r++) {
g = rotateLeft(u, 5) + (c & p | c & f | p & f) + m + h[r] + l & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
for (r = 60; 80 > r; r++) {
g = rotateLeft(u, 5) + (c ^ p ^ f) + m + h[r] + d & 4294967295,
m = f,
f = p,
p = rotateLeft(c, 30),
c = u,
u = g
}
e.A = e.A + u & 4294967295,
e.B = e.B + c & 4294967295,
e.C = e.C + p & 4294967295,
e.D = e.D + f & 4294967295,
e.E = e.E + m & 4294967295
}
function rotateLeft(e, t) {
var i = e >>> 32 - t
, r = (1 << 32 - t) - 1
, n = e & r;
return n << t | i
}
function hexStringToMP(e) {
var t, i, r = Math.ceil(e.length / 4), n = new JSMPnumber;
for (n.size = r,
t = 0; r > t; t++) {
i = e.substr(4 * t, 4),
n.data[r - 1 - t] = parseInt(i, 16)
}
return n
}
function duplicateMP(e) {
var t = new JSMPnumber;
return t.size = e.size,
t.data = e.data.slice(0),
t
}
function mpToByteArray(e) {
var t = []
, i = 0
, r = e.size;
for (i = 0; r > i; i++) {
t[2 * i] = 255 & e.data[i];
var n = e.data[i] >>> 8;
t[2 * i + 1] = n
}
return t
}
function byteArrayToBase64(e) {
var t, i, r = e.length, n = "";
for (t = r - 3; t >= 0; t -= 3) {
i = e[t] | e[t + 1] << 8 | e[t + 2] << 16,
n += base64Encode(i, 4)
}
var o = r % 3;
for (i = 0,
t += 2; t >= 0; t--) {
i = i << 8 | e[t]
}
return 1 == o ? n = n + base64Encode(i << 16, 2) + "==" : 2 == o && (n = n + base64Encode(i << 8, 3) + "="),
n
}
function base64Encode(e, t) {
var i, r = "";
for (i = t; 4 > i; i++) {
e >>= 6
}
for (i = 0; t > i; i++) {
r = mapByteToBase64(63 & e) + r,
e >>= 6
}
return r
}
function mapByteToBase64(e) {
return e >= 0 && 26 > e ? String.fromCharCode(65 + e) : e >= 26 && 52 > e ? String.fromCharCode(97 + e - 26) : e >= 52 && 62 > e ? String.fromCharCode(48 + e - 52) : 62 == e ? "+" : "/"
}
var Key = "e=10001;m=ba71796836ba1c27cb30c23f3192d3e610e4df4e0253eca914c162063a3041d50c40a60767e7e4941ec6a4bc426adc5827f859eeb8df1c7dca96adb4fd8d446d80d1a29c9349f92b4f33f3c2c5f852bfe5db90ad75095d847093320c1ffc4bff6ee04da1b7f375913e0e176fe654302ad8c8e379432af022e6411eb764c5c1f25c26b06244978470b7d58164d7191427ee09e058aca452ee6b4bcdde014d711fd14ba2341fca26bcf7f13292238eeffdd45b077e3004d9f472e34b1dbf2dfde0da3afcd5e89f12660396b8bf399a783a166efb4068d4b5e5a024defaf9884366025fb11ab543aec9032dd95c31e2e57e77f0370cfe8fb4c1812a917c4ade221b"
var randomNum = "AA278C7C00D44877AA95055BB0497A6169195B7B79C664E0AC9DFDCE1112CE28282BAA83D5CD95041CB512CD35624CCD6FD873C98579E4D3C4D25E5E6134F65628BDA9DE9C00A6E53A0194EA7483BCB1AABD8AA983282259E2953CC8705D36BB9936E57E"
var ciphertextB64FromJS = Encrypt(null, "1234", "saproof");
document.getElementById("js_enc").innerHTML = "JavaScript code (encryption): " + ciphertextB64FromJS;
// Decryption ======================================================================================================================================================
// Decryption of a ciphertext from the JavaScript Code
var decryptedCiphertextFromJS = await decrypt(ciphertextB64FromJS);
document.getElementById("js_dec").innerHTML = "JavaScript code (decryption): " + decryptedCiphertextFromJS;
// Decryption of a ciphertext from the Python code for encryption
var ciphertextB64FromPy = 'iQefWJtEXRjMpJj59NmODmDVuJJkmsSV2pNvPrAX74lDWiXHjY4H34XAEGHY5bJ/3xJ3f7pM1R0Nb8cBJSgQMpCO/0PCdDSbalw7M/cbEEOzrIVMxg8NXOsUM6tqetaroSAutyesg8+EsP4liow3ssV6I7cX/QDpunFV0vRHxTM9Am35QNrNfpvZMu4kV642dq9ocSJLdbaBfaKXUyBA6nYzUIhq3nHx8XzPxo9DnAoE6qkGeRpQzV7Mo+jeY26YOP/DyVmb0JuOXPI8Uz/4yxhQp7ygAVOF5CNojZN0XtZVqORV4+2bFEMD+Fi9YIIFFMrym169ACoy2faTfLYjlw=='; // MAKE SURE TO USE THE CORRECT PUBLIC KEY DURING ENCRYPTION!!!: modulus = 0xba717968..., public exponent = 0x10001 (s. above)
var decryptedCiphertextFromPy = await decrypt(ciphertextB64FromPy);
document.getElementById("py_dec").innerHTML = "Python code (decryption): " + decryptedCiphertextFromPy;
async function decrypt(ciphertextBase64){
var pkcs8Der = b642ab('MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6cXloNrocJ8swwj8xktPmEOTfTgJT7KkUwWIGOjBB1QxApgdn5+SUHsakvEJq3Fgn+FnuuN8cfcqWrbT9jURtgNGinJNJ+StPM/PCxfhSv+XbkK11CV2EcJMyDB/8S/9u4E2ht/N1kT4OF2/mVDAq2MjjeUMq8CLmQR63ZMXB8lwmsGJEl4Rwt9WBZNcZFCfuCeBYrKRS7mtLzd4BTXEf0UuiNB/KJrz38TKSI47v/dRbB34wBNn0cuNLHb8t/eDaOvzV6J8SZgOWuL85mng6Fm77QGjUteWgJN76+YhDZgJfsRq1Q67JAy3ZXDHi5X538DcM/o+0wYEqkXxK3iIbAgMBAAECggEASlJj0ExIomKmmBhG8q8SM1s2sWG6gdQMjs6MEeluRT/1c2v79cq2Dum5y/+UBl8x8TUKPKSLpCLs+GXkiVKgHXrFlqoN+OYQArG2EUWzuODwczdYPhhupBXwR3oX4g41k/BsYfQfZBVzBFEJdWrIDLyAUFWNlfdGIj2BTiAoySfyqmamvmW8bsvc8coiGlZ28UC85/Xqx9wOzjeGoRkCH7PcTMlc9F7SxSthwX/k1VBXmNOHa+HzGOgO/W3k1LDqJbq2wKjZTW3iVEg2VodjxgBLMm0MueSGoI6IuaZSPMyFEM3gGvC2+cDBI2SL/amhiTUa/VDlTVw/IKbSuar9uQKBgQDd76M0Po5Lqh8ZhQ3obhFqkfO5EBXy7HUL15cw51kVtwF6Gf/J2HNHjwsg9Nb0eJETTS6bbuVd9bn884JoRS986nVTFNZ4dnjEgKjjQ8GjfzdkpbUxsRLWiIxuOQSpIUZGdMi2ctTTtspvMsDsjRRYdYIQCe/SDsdHGT3vcUCybwKBgQDXDz6iVnY84Fh5iDDVrQOR4lYoxCL/ikCDJjC6y1mjR0eVFdBPQ4j1dDSPU9lahBLby0VyagQCDp/kxQOl0z2zBLRI4I8jUtz9/9KW6ze7U7dQJ7OTfumd5I97OyQOG9XZwKUkRgfyb/PAMBSUSLgosi38f+OC3IN3qlvHFzvxFQKBgQCITpUDEmSczih5qQGIvolN1cRF5j5Ey7t7gXbnXz+Umah7kJpMIvdyfMVOAXJABgi8PQwiBLM0ySXo2LpARjXLV8ilNUggBktYDNktc8DrJMgltayaj3HNd2IglD5rjfc2cKWRgOd7/GlKcHaTEnbreYhfR2sWrWLxJOyoMfuVWwKBgFalCbMV6qU0LfEo8aPlBN8ttVDPVNpntP4h0NgxPXgPK8Pg+gA1UWSy4MouGg/hzkdHaj9ifyLlCX598a5JoT4S0x/ZeVHd/LNI8mtjcRzD6cMde7gdFbpLb5NSjIAyrsIAX4hxvpnqiOYRePkVIz0iLGziiaMbfMwlkrxvm/LRAoGBALPRbtSbE2pPgvOHKHTGPr7gKbmsWVbOcQA8rG801T38W/UPe1XtynMEjzzQ29OaVeQwvUN9+DxFXJ6Yvwj6ih4Wdq109i7Oo1fDnMczOQN9DKch2eNAHrNSOMyLDCBm++wbyHAsS2T0VO8+gzLABviZm5AFCQWfke4LZo5mOS10');
var privateKey = await window.crypto.subtle.importKey("pkcs8", pkcs8Der, {name: "RSA-OAEP", hash: "SHA-1"}, true, ["decrypt"]);
var ciphertext = b642ab(ciphertextBase64);
ciphertext = ciphertext.reverse(); // reverse little endian order
var decrypted = await window.crypto.subtle.decrypt({name: "RSA-OAEP"}, privateKey, ciphertext); // apply OAEP as padding
return decodeUTF16LE(decrypted); // decode with UTF-16LE
}
// Helper
function b642ab(base64_string){
return Uint8Array.from(window.atob(base64_string), c => c.charCodeAt(0));
}
// https://stackoverflow.com/a/14601808
function decodeUTF16LE(buf) {
var cp = [];
var binaryStr = String.fromCharCode.apply(null, new Uint8Array(buf));
for( var i = 0; i < binaryStr.length; i+=2) {
cp.push(
binaryStr.charCodeAt(i) |
( binaryStr.charCodeAt(i+1) << 8 )
);
}
return String.fromCharCode.apply( String, cp );
}
})();
<p style="font-family:'Courier New', monospace;" id="js_enc"></p>
<p style="font-family:'Courier New', monospace;" id="js_dec"></p>
<p style="font-family:'Courier New', monospace;" id="py_dec"></p>

Javascript RSA implementation doesn't generate correctly

The problem is at generating either e or d. But what? The math seems good to me.
e > 1 and coprime to ϕ
d satisfies de≡1(modϕ(n))
Please help
var m = 4, //Message
p = 13
q = 7
n = p * q
T = (q - 1) * (p - 1)
d = new Number;
//Calculate e:
for (let i = 2; i < T; i++) {
if( (gcd(i,T) == 1) ) { var e = i; break; }
}
//Calculate d:
while ( e * d % T != 1 ) d++;
function gcd(k, n) {
return k ? gcd(n % k, k) : n;
}
var e_m = m ** e % n, // To encrypt
d_m = e_m ** d % n // To decrypt
console.log(`m: ${m}\np: ${p}\nq: ${q}\nn: ${n}\nT: ${T}\n\ne: ${e}\nd: ${d}\n\nencrypted: ${e_m}\ndecrypted: ${d_m}`);
//Results:
// encrypted: 23
// decrypted: 28 (not 4)

Need assistance in understanding javascript order of precedence

I'm having an issue understanding how the following statement is working.
// setup
var n = 3;
var J = 3;
var g = 0;
var p = 41;
var m = false;
var O = 22;
var z = 15;
var I = [7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,21,19,20,22,18,20,19,21,7,7,17,17,17,17,17,17,17,17,7,7,0,0,0,0,0,0,0,0,7,7,0,0,0,0,0,0,0,0,7,7,0,0,0,0,0,0,0,0,7,7,0,0,0,0,0,0,0,0,7,7,25,25,25,25,25,25,25,25,7,7,29,27,28,30,26,28,27,29,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,,22]
// statement
n += J || (g = p, m = p < O ? g - 3 : g + 2, I[m] < z | I[m + O - p] || I[p += p - O]) ? 1 : 0;
At the end of the statement n=4 but I don't understand how or why. I would expect:
n += 3 || 1 // n = 6
This is someone else's code I'm trying to understand. Any help is appreciated.
Let's simplify your expression a little.
n += X || Y ? 1 : 0
where
X = J
Y = (g = p, m = p < O ? g - 3 : g + 2, I[m] < z | I[m + O - p] || I[p += p - O])
Here we can see that we are evaluating X || Y and, on the basis of this, the ternary operator ? returns a value of either 1 or 0.
Since X || Y evaluates to true, we get n += 1 impliying that n = 4.
It's quite simple.
J || (g = p, m = p < O ? g - 3 : g + 2, I[m] < z | I[m + O - p] || I[p += p - O]) ? 1 : 0
This above equals (J || anything) ? 1 : 0. Since J=3, it's like (3 || anything) ? 1 : 0.
n += 3 || anything ? 1 : 0 -> n += 1

Generating the same SHA1 UUID in golang and Javascript

I have what I thought was a pretty simply question. I'm using this code to generate a SHA1 uuid in Golang:
namespace := uuid.Parse("b9cfdb9d-f741-4e1f-89ae-fac6b2a5d740")
sha := uuid.NewSHA1(namespace, []byte("something"))
fmt.Println(sha.String())
Now I want to generate the same UUID in javascript, and I thought it would be as easy as something like this:
var hash = CryptoJS.SHA1("b9cfdb9d-f741-4e1f-89ae-fac6b2a5d740" + "something")
// chomp the hash into a UUID string
However, I'm running into serious issues. It seems that the uuid.Parse function in Golang is running this parsing function that converts the namespace to a 16-byte array, so even though I use the same SHA1 algorithm in Javascript, I'm not getting the same output.
I'v been messing around with doing the same in JS, but I'm stumped.
Any smart crypto people in here that can help me?
Well, that only took me a month.
var SHA1Generator = {
hex_chr: "0123456789abcdef",
hex: function (num) {
var str = "";
for (var j = 7; j >= 0; j--)
str += this.hex_chr.charAt((num >> (j * 4)) & 0x0F);
return str;
},
str2blks_SHA1: function (str) {
var nblk = ((str.length + 8) >> 6) + 1;
var blks = new Array(nblk * 16);
for (var i = 0; i < nblk * 16; i++) blks[i] = 0;
for (i = 0; i < str.length; i++)
blks[i >> 2] |= str.charCodeAt(i) << (24 - (i % 4) * 8);
blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8);
blks[nblk * 16 - 1] = str.length * 8;
return blks;
},
add: function (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
},
rol: function (num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
},
ft: function (t, b, c, d) {
if (t < 20) return (b & c) | ((~b) & d);
if (t < 40) return b ^ c ^ d;
if (t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
},
kt: function (t) {
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
},
calcSHA1FromByte: function(byteArr) {
var str = '';
for(var i=0; i<byteArr.length; i++)
str += String.fromCharCode(byteArr[i]);
return this.calcSHA1(str);
},
calcSHA1: function (str) {
if (str != '') {
var x = this.str2blks_SHA1(str);
var w = new Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for (var i = 0; i < x.length; i += 16) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = x[i + j];
else w[j] = this.rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
t = this.add(this.add(this.rol(a, 5), this.ft(j, b, c, d)), this.add(this.add(e, w[j]), this.kt(j)));
e = d;
d = c;
c = this.rol(b, 30);
b = a;
a = t;
}
a = this.add(a, olda);
b = this.add(b, oldb);
c = this.add(c, oldc);
d = this.add(d, oldd);
e = this.add(e, olde);
}
return this.hex(a) + this.hex(b) + this.hex(c) + this.hex(d) + this.hex(e);
}
else {
return '';
}
}
};
function stringToByteArray(str) {
var bytes = [];
for (var i = 0; i < str.length; ++i) {
bytes.push(str.charCodeAt(i));
}
return bytes;
}
function uuidToByteArray(hex) {
// If this is a uuid, remove the dashes
hex = hex.replace(/-/g, "");
// convert each hex number into a string representation
// of the byte integer.
var bytes = [];
for(var i = 0; i < hex.length; i += 2) {
bytes.push(parseInt(hex.substring(i, i+2),16));
}
return bytes;
}
function sha1ToUUID5(hash) {
var uuid = hash.substring(0, 8) +
'-' + hash.substring(8, 12) +
// four most significant bits holds version number 5
'-' + ((parseInt(hash.substring(12, 16), 16) & 0x0fff) | 0x5000).toString(16) +
// two most significant bits holds zero and one for variant DCE1.1
'-' + ((parseInt(hash.substring(16, 20), 16) & 0x3fff) | 0x8000).toString(16) +
'-' + hash.substring(20, 32); //12 digits
return uuid;
}
var namespace = "e75a36a9-3323-40dd-a7d1-1c57ad2aa3cd"
var id = "event154"
var namespaceBytes = uuidToByteArray(namespace);
var idBytes = stringToByteArray(id);
var allBytes = namespaceBytes.concat(idBytes);
console.log("ORG 4505612c-c323-5d6f-b5cc-b7f362b9ba55")
console.log("NEW " + sha1ToUUID5(SHA1Generator.calcSHA1FromByte(allBytes)))

Get SHA1 checksum of byte array in JavaScript?

So I need to get a SHA1 hash of a byte array in javascript (Will be array of integer values 0-255), I can't seem to figure out how to achive this.
I need to be able to get the same result as the C# SHA1.ComputeHash function, meaning I input a byte array and get a 20 byte array back representing the resulting checksum.
Does anyone have a way to achieve this?
Thanks!
Use the calcSHA1FromByte function to get the sha1 of a byte array
var SHA1Generator = {
hex_chr: "0123456789abcdef",
hex: function (num) {
var str = "";
for (var j = 7; j >= 0; j--)
str += this.hex_chr.charAt((num >> (j * 4)) & 0x0F);
return str;
},
str2blks_SHA1: function (str) {
var nblk = ((str.length + 8) >> 6) + 1;
var blks = new Array(nblk * 16);
for (var i = 0; i < nblk * 16; i++) blks[i] = 0;
for (i = 0; i < str.length; i++)
blks[i >> 2] |= str.charCodeAt(i) << (24 - (i % 4) * 8);
blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8);
blks[nblk * 16 - 1] = str.length * 8;
return blks;
},
add: function (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
},
rol: function (num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
},
ft: function (t, b, c, d) {
if (t < 20) return (b & c) | ((~b) & d);
if (t < 40) return b ^ c ^ d;
if (t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
},
kt: function (t) {
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
},
calcSHA1FromByte: function(byteArr) {
var str = '';
for(var i=0; i<byteArr.length; i++)
str += String.fromCharCode(byteArr[i]);
return this.calcSHA1(str);
},
calcSHA1: function (str) {
if (str != '') {
var x = this.str2blks_SHA1(str);
var w = new Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for (var i = 0; i < x.length; i += 16) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = x[i + j];
else w[j] = this.rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
t = this.add(this.add(this.rol(a, 5), this.ft(j, b, c, d)), this.add(this.add(e, w[j]), this.kt(j)));
e = d;
d = c;
c = this.rol(b, 30);
b = a;
a = t;
}
a = this.add(a, olda);
b = this.add(b, oldb);
c = this.add(c, oldc);
d = this.add(d, oldd);
e = this.add(e, olde);
}
return this.hex(a) + this.hex(b) + this.hex(c) + this.hex(d) + this.hex(e);
}
else {
return '';
}
}
};
// your byte array
var byteArr = ['100','101','114'];
var sha1 = SHA1Generator.calcSHA1FromByte(byteArr);

Categories