Added async modPow worker
This commit is contained in:
parent
d150de0bc5
commit
45f3798794
@ -516,3 +516,17 @@ function pqPrimeLeemon (what) {
|
|||||||
|
|
||||||
return [bytesFromLeemonBigInt(P), bytesFromLeemonBigInt(Q), it];
|
return [bytesFromLeemonBigInt(P), bytesFromLeemonBigInt(Q), it];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function bytesModPow (x, y, m) {
|
||||||
|
try {
|
||||||
|
var xBigInt = str2bigInt(x, 64),
|
||||||
|
yBigInt = str2bigInt(y, 64),
|
||||||
|
mBigInt = str2bigInt(bytesToHex(m), 16, 2),
|
||||||
|
resBigInt = powMod(xBigInt, yBigInt, mBigInt);
|
||||||
|
|
||||||
|
return bytesFromHex(bigInt2str(resBigInt, 16));
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
return bytesFromBigInt(new BigInteger(x).modPow(new BigInteger(y), new BigInteger(m)));
|
||||||
|
}
|
||||||
|
17
app/js/lib/mp_worker.js
Normal file
17
app/js/lib/mp_worker.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*!
|
||||||
|
* Webogram v0.2 - messaging web application for MTProto
|
||||||
|
* https://github.com/zhukov/webogram
|
||||||
|
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
||||||
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
importScripts(
|
||||||
|
'../../vendor/console-polyfill/console-polyfill.js',
|
||||||
|
'bin_utils.js',
|
||||||
|
'../../vendor/leemon_bigint/bigint.js',
|
||||||
|
'../../vendor/jsbn/jsbn_combined.js'
|
||||||
|
);
|
||||||
|
|
||||||
|
onmessage = function (e) {
|
||||||
|
postMessage(bytesModPow(e.data[0], e.data[1], e.data[2]));
|
||||||
|
}
|
@ -85,9 +85,7 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
|||||||
var fingerprintBytes = sha1Hash(buffer).slice(-8);
|
var fingerprintBytes = sha1Hash(buffer).slice(-8);
|
||||||
fingerprintBytes.reverse();
|
fingerprintBytes.reverse();
|
||||||
|
|
||||||
var fingerprint = new BigInteger(fingerprintBytes).toString(16);
|
publicKeysParsed[bytesToHex(fingerprintBytes)] = {
|
||||||
|
|
||||||
publicKeysParsed[fingerprint] = {
|
|
||||||
modulus: keyParsed.modulus,
|
modulus: keyParsed.modulus,
|
||||||
exponent: keyParsed.exponent
|
exponent: keyParsed.exponent
|
||||||
};
|
};
|
||||||
@ -404,108 +402,132 @@ angular.module('izhukov.mtproto', ['izhukov.utils'])
|
|||||||
MtpMessageIdGenerator.applyServerTime(auth.serverTime, auth.localTime);
|
MtpMessageIdGenerator.applyServerTime(auth.serverTime, auth.localTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function mtpAsyncModPow (x, y, m) {
|
||||||
|
console.log(dT(), 'modPow start');
|
||||||
|
if (!window.Worker) {
|
||||||
|
var result = bytesModPow(x, y, m);
|
||||||
|
console.log(dT(), 'sync modPow done');
|
||||||
|
return $q.when(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
var deferred = $q.defer(),
|
||||||
|
worker = new Worker('js/lib/mp_worker.js');
|
||||||
|
|
||||||
|
worker.onmessage = function (e) {
|
||||||
|
console.log(dT(), 'async modPow done');
|
||||||
|
deferred.resolve(e.data);
|
||||||
|
};
|
||||||
|
worker.onerror = function(error) {
|
||||||
|
console.log('Worker error', error, error.stack);
|
||||||
|
deferred.reject(error);
|
||||||
|
};
|
||||||
|
worker.postMessage([x, y, m]);
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
function mtpSendSetClientDhParams(auth) {
|
function mtpSendSetClientDhParams(auth) {
|
||||||
var deferred = auth.deferred;
|
var deferred = auth.deferred,
|
||||||
|
gBytes = bytesFromHex(auth.g.toString(16));
|
||||||
|
|
||||||
auth.b = new Array(256);
|
auth.b = new Array(256);
|
||||||
MtpSecureRandom.nextBytes(auth.b);
|
MtpSecureRandom.nextBytes(auth.b);
|
||||||
|
|
||||||
var bBigInt = new BigInteger(auth.b);
|
mtpAsyncModPow(gBytes, auth.b, auth.dhPrime).then(function (gB) {
|
||||||
var dhPrimeBigInt = new BigInteger(auth.dhPrime);
|
|
||||||
|
|
||||||
var gB = bytesFromBigInt(bigint(auth.g).modPow(bBigInt, dhPrimeBigInt));
|
var data = new TLSerialization({mtproto: true});
|
||||||
|
data.storeObject({
|
||||||
|
_: 'client_DH_inner_data',
|
||||||
|
nonce: auth.nonce,
|
||||||
|
server_nonce: auth.serverNonce,
|
||||||
|
retry_id: [0, auth.retry++],
|
||||||
|
g_b: gB,
|
||||||
|
}, 'Client_DH_Inner_Data');
|
||||||
|
|
||||||
var data = new TLSerialization({mtproto: true});
|
var dataWithHash = sha1Hash(data.getBuffer()).concat(data.getBytes());
|
||||||
data.storeObject({
|
|
||||||
_: 'client_DH_inner_data',
|
|
||||||
nonce: auth.nonce,
|
|
||||||
server_nonce: auth.serverNonce,
|
|
||||||
retry_id: [0, auth.retry++],
|
|
||||||
g_b: gB,
|
|
||||||
}, 'Client_DH_Inner_Data');
|
|
||||||
|
|
||||||
var dataWithHash = sha1Hash(data.getBuffer()).concat(data.getBytes());
|
var encryptedData = aesEncrypt(dataWithHash, auth.tmpAesKey, auth.tmpAesIv);
|
||||||
|
|
||||||
var encryptedData = aesEncrypt(dataWithHash, auth.tmpAesKey, auth.tmpAesIv);
|
var request = new TLSerialization({mtproto: true});
|
||||||
|
request.storeMethod('set_client_DH_params', {
|
||||||
|
nonce: auth.nonce,
|
||||||
|
server_nonce: auth.serverNonce,
|
||||||
|
encrypted_data: encryptedData
|
||||||
|
});
|
||||||
|
|
||||||
var request = new TLSerialization({mtproto: true});
|
console.log(dT(), 'Send set_client_DH_params');
|
||||||
request.storeMethod('set_client_DH_params', {
|
mtpSendPlainRequest(auth.dcID, request.getBuffer()).then(function (result) {
|
||||||
nonce: auth.nonce,
|
var deserializer = result.data;
|
||||||
server_nonce: auth.serverNonce,
|
var response = deserializer.fetchObject('Set_client_DH_params_answer');
|
||||||
encrypted_data: encryptedData
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(dT(), 'Send set_client_DH_params');
|
if (response._ != 'dh_gen_ok' && response._ != 'dh_gen_retry' && response._ != 'dh_gen_fail') {
|
||||||
mtpSendPlainRequest(auth.dcID, request.getBuffer()).then(function (result) {
|
deferred.reject(new Error('Set_client_DH_params_answer response invalid: ' + response._));
|
||||||
var deserializer = result.data;
|
|
||||||
var response = deserializer.fetchObject('Set_client_DH_params_answer');
|
|
||||||
|
|
||||||
if (response._ != 'dh_gen_ok' && response._ != 'dh_gen_retry' && response._ != 'dh_gen_fail') {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer response invalid: ' + response._));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bytesCmp (auth.nonce, response.nonce)) {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer nonce mismatch'));
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bytesCmp (auth.serverNonce, response.server_nonce)) {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer server_nonce mismatch'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var bBigInt = new BigInteger(auth.b);
|
|
||||||
var dhPrimeBigInt = new BigInteger(auth.dhPrime);
|
|
||||||
|
|
||||||
var authKey = bytesFromBigInt((new BigInteger(auth.gA)).modPow(bBigInt, dhPrimeBigInt)),
|
|
||||||
authKeyHash = sha1Hash(authKey),
|
|
||||||
authKeyAux = authKeyHash.slice(0, 8),
|
|
||||||
authKeyID = authKeyHash.slice(-8);
|
|
||||||
|
|
||||||
console.log(dT(), 'Got Set_client_DH_params_answer', response._);
|
|
||||||
switch (response._) {
|
|
||||||
case 'dh_gen_ok':
|
|
||||||
var newNonceHash1 = sha1Hash(auth.newNonce.concat([1], authKeyAux)).slice(-16);
|
|
||||||
|
|
||||||
if (!bytesCmp(newNonceHash1, response.new_nonce_hash1)) {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash1 mismatch'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
|
||||||
// console.log('Auth successfull!', authKeyID, authKey, serverSalt);
|
|
||||||
|
|
||||||
auth.authKeyID = authKeyID;
|
|
||||||
auth.authKey = authKey;
|
|
||||||
auth.serverSalt = serverSalt;
|
|
||||||
|
|
||||||
deferred.resolve(auth);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'dh_gen_retry':
|
|
||||||
var newNonceHash2 = sha1Hash(auth.newNonce.concat([2], authKeyAux)).slice(-16);
|
|
||||||
if (!bytesCmp(newNonceHash2, response.new_nonce_hash2)) {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash2 mismatch'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mtpSendSetClientDhParams(auth);
|
|
||||||
|
|
||||||
case 'dh_gen_fail':
|
|
||||||
var newNonceHash3 = sha1Hash(auth.newNonce.concat([3], authKeyAux)).slice(-16);
|
|
||||||
if (!bytesCmp(newNonceHash3, response.new_nonce_hash3)) {
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash3 mismatch'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
deferred.reject(new Error('Set_client_DH_params_answer fail'));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytesCmp (auth.nonce, response.nonce)) {
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer nonce mismatch'));
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bytesCmp (auth.serverNonce, response.server_nonce)) {
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer server_nonce mismatch'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mtpAsyncModPow(auth.gA, auth.b, auth.dhPrime).then(function (authKey) {
|
||||||
|
var authKeyHash = sha1Hash(authKey),
|
||||||
|
authKeyAux = authKeyHash.slice(0, 8),
|
||||||
|
authKeyID = authKeyHash.slice(-8);
|
||||||
|
|
||||||
|
console.log(dT(), 'Got Set_client_DH_params_answer', response._);
|
||||||
|
switch (response._) {
|
||||||
|
case 'dh_gen_ok':
|
||||||
|
var newNonceHash1 = sha1Hash(auth.newNonce.concat([1], authKeyAux)).slice(-16);
|
||||||
|
|
||||||
|
if (!bytesCmp(newNonceHash1, response.new_nonce_hash1)) {
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash1 mismatch'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
||||||
|
// console.log('Auth successfull!', authKeyID, authKey, serverSalt);
|
||||||
|
|
||||||
|
auth.authKeyID = authKeyID;
|
||||||
|
auth.authKey = authKey;
|
||||||
|
auth.serverSalt = serverSalt;
|
||||||
|
|
||||||
|
deferred.resolve(auth);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'dh_gen_retry':
|
||||||
|
var newNonceHash2 = sha1Hash(auth.newNonce.concat([2], authKeyAux)).slice(-16);
|
||||||
|
if (!bytesCmp(newNonceHash2, response.new_nonce_hash2)) {
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash2 mismatch'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mtpSendSetClientDhParams(auth);
|
||||||
|
|
||||||
|
case 'dh_gen_fail':
|
||||||
|
var newNonceHash3 = sha1Hash(auth.newNonce.concat([3], authKeyAux)).slice(-16);
|
||||||
|
if (!bytesCmp(newNonceHash3, response.new_nonce_hash3)) {
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer new_nonce_hash3 mismatch'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferred.reject(new Error('Set_client_DH_params_answer fail'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, function (error) {
|
||||||
|
deferred.reject(error);
|
||||||
|
})
|
||||||
|
}, function (error) {
|
||||||
|
deferred.reject(error);
|
||||||
|
});
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
deferred.reject(error);
|
deferred.reject(error);
|
||||||
});
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
var cached = {};
|
var cached = {};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user