Skip to content

Commit

Permalink
Increase the code quality
Browse files Browse the repository at this point in the history
  • Loading branch information
enricostara committed Nov 28, 2014
1 parent 5d4fcd9 commit bab1af0
Showing 1 changed file with 85 additions and 40 deletions.
125 changes: 85 additions & 40 deletions lib/telegram.link.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ TelegramLink.prototype.authorization = function (callback) {
encryptPQInnerDataWithRSA,
requestDHParams,
decryptDHParams,
deserializeDHInnerData,
createClientDHInnerData,
encryptClientDHInnerDataWithAES,
setClientDHParams
Expand All @@ -79,7 +80,7 @@ TelegramLink.prototype.authorization = function (callback) {
},
conn: connection,
callback: function (ex, resPQ) {
if (clientNonce == resPQ.nonce) {
if (clientNonce === resPQ.nonce) {
callback(null, resPQ);
} else {
callback(createError('Nonce mismatch.', 'ENONCE'));
Expand All @@ -91,9 +92,13 @@ TelegramLink.prototype.authorization = function (callback) {
// Find the P and Q prime numbers
function findPAndQ(resPQ) {
var pqFinder = new security.PQFinder(resPQ.pq);
if (logger.isDebugEnabled()) logger.debug('Start finding P and Q, with PQ = %s', pqFinder.getPQPairNumber());
if (logger.isDebugEnabled()) {
logger.debug('Start finding P and Q, with PQ = %s', pqFinder.getPQPairNumber());
}
var pq = pqFinder.findPQ();
if (logger.isDebugEnabled()) logger.debug('Found P = %s and Q = %s', pq[0], pq[1]);
if (logger.isDebugEnabled()) {
logger.debug('Found P = %s and Q = %s', pq[0], pq[1]);
}
return {
pBuffer: pqFinder.getPQAsBuffer()[0],
qBuffer: pqFinder.getPQAsBuffer()[1],
Expand All @@ -104,13 +109,19 @@ TelegramLink.prototype.authorization = function (callback) {
// Find the correct Public Key using fingerprint from server response
function findPublicKey(obj) {
var fingerprints = obj.resPQ.server_public_key_fingerprints.getList();
if (logger.isDebugEnabled()) logger.debug('Public keys fingerprints from server: %s', fingerprints);
if (logger.isDebugEnabled()) {
logger.debug('Public keys fingerprints from server: %s', fingerprints);
}
for (var i = 0; i < fingerprints.length; i++) {
var fingerprint = fingerprints[i];
if (logger.isDebugEnabled()) logger.debug('Searching fingerprint %s in store', fingerprint);
if (logger.isDebugEnabled()) {
logger.debug('Searching fingerprint %s in store', fingerprint);
}
var publicKey = security.PublicKey.retrieveKey(fingerprint);
if (publicKey) {
if (logger.isDebugEnabled()) logger.debug('Fingerprint %s found in keyStore.', fingerprint);
if (logger.isDebugEnabled()) {
logger.debug('Fingerprint %s found in keyStore.', fingerprint);
}
obj.fingerprint = fingerprint;
obj.publicKey = publicKey;
return obj;
Expand Down Expand Up @@ -141,9 +152,10 @@ TelegramLink.prototype.authorization = function (callback) {
// Create the data with hash to be encrypt
var hash = utility.createSHA1Hash(obj.pqInnerData);
var dataWithHash = Buffer.concat([hash, obj.pqInnerData]);
if (logger.isDebugEnabled()) logger.debug('Data to be encrypted contains: ' +
'hash(%s), pqInnerData(%s), total length %s',
hash.length, obj.pqInnerData.length, dataWithHash.length);
if (logger.isDebugEnabled()) {
logger.debug('Data to be encrypted contains: hash(%s), pqInnerData(%s), total length %s',
hash.length, obj.pqInnerData.length, dataWithHash.length);
}
// Encrypt data with RSA
obj.encryptedData = security.cipher.rsaEncrypt(dataWithHash, obj.publicKey);
return obj;
Expand All @@ -165,13 +177,18 @@ TelegramLink.prototype.authorization = function (callback) {
callback: function (ex, serverDHParams, duration) {
if (ex) {
logger.error(ex);
if (callback) callback(ex);
if (callback) {
callback(ex);
}
} else {
if (serverDHParams.typeName == 'mtproto.type.Server_DH_params_ok') {
if (logger.isDebugEnabled()) logger.debug('\'Server_DH_params_ok\' received from Telegram.');
if (serverDHParams.typeName === 'mtproto.type.Server_DH_params_ok') {
if (logger.isDebugEnabled()) {
logger.debug('\'Server_DH_params_ok\' received from Telegram.');
}
obj.serverDHParams = serverDHParams;
callback(null, obj, duration);
} else if (serverDHParams.typeName == 'mtproto.type.Server_DH_params_ko') {
obj.reqDHDuration = duration;
callback(null, obj);
} else if (serverDHParams.typeName === 'mtproto.type.Server_DH_params_ko') {
logger.warn('\'Server_DH_params_ko\' received from Telegram!');
callback(createError(JSON.stringify(serverDHParams), 'EDHPARAMKO'));
} else {
Expand All @@ -185,43 +202,62 @@ TelegramLink.prototype.authorization = function (callback) {
}

// Decrypt DH parameters and synch the local time with the server time
function decryptDHParams(obj, duration) {
function decryptDHParams(obj) {
var newNonce = TypeObject.stringValue2Buffer(obj.newNonce, 32);
var serverNonce = TypeObject.stringValue2Buffer(obj.resPQ.server_nonce, 16);
if (logger.isDebugEnabled()) logger.debug('newNonce = %s, serverNonce = %s', newNonce.toString('hex'), serverNonce.toString('hex'));
if (logger.isDebugEnabled()) {
logger.debug('newNonce = %s, serverNonce = %s', newNonce.toString('hex'), serverNonce.toString('hex'));
}
var hashNS = utility.createSHA1Hash([newNonce, serverNonce]);
var hashSN = utility.createSHA1Hash([serverNonce, newNonce]);
var hashNN = utility.createSHA1Hash([newNonce, newNonce]);
if (logger.isDebugEnabled()) logger.debug('hashNS = %s, hashSN = %s, hashNN = %s', hashNS.toString('hex'), hashSN.toString('hex'), hashNN.toString('hex'));
if (logger.isDebugEnabled()) {
logger.debug('hashNS = %s, hashSN = %s, hashNN = %s',
hashNS.toString('hex'), hashSN.toString('hex'), hashNN.toString('hex'));
}
// Create the AES key
var aesKey = Buffer.concat([hashNS, hashSN.slice(0, 12)]);
var aesIv = Buffer.concat([Buffer.concat([hashSN.slice(12), hashNN]), newNonce.slice(0, 4)]);
if (logger.isDebugEnabled()) logger.debug('aesKey = %s, aesIv = %s', aesKey.toString('hex'), aesIv.toString('hex'));
if (logger.isDebugEnabled()) {
logger.debug('aesKey = %s, aesIv = %s', aesKey.toString('hex'), aesIv.toString('hex'));
}
// Decrypt the message
var answerWithHash = security.cipher.aesDecrypt(
obj.serverDHParams.encrypted_answer,
aesKey,
aesIv
);
obj.decryptedDHParams = answerWithHash;
// Save AES key
obj.aes = {key: aesKey, iv: aesIv};
// De-serialize the inner data
if (logger.isDebugEnabled()) logger.debug('answerWithHash(%s) = %s', answerWithHash.length, answerWithHash.toString('hex'));
var answer = answerWithHash.slice(20, 564 + 20);
if (logger.isDebugEnabled()) logger.debug('answer(%s) = %s', answer.length, answer.toString('hex'));
return obj;
}

// De-serialize the server DH inner data
function deserializeDHInnerData(obj) {
var decryptedDHParamsWithHash = obj.decryptedDHParams;
if (logger.isDebugEnabled()) {
logger.debug('decryptedDHParamsWithHash(%s) = %s', decryptedDHParamsWithHash.length, decryptedDHParamsWithHash.toString('hex'));
}
var decryptedDHParams = decryptedDHParamsWithHash.slice(20, 564 + 20);
if (logger.isDebugEnabled()) {
logger.debug('decryptedDHParams(%s) = %s', decryptedDHParams.length, decryptedDHParams.toString('hex'));
}
var serverDHInnerData = new mtproto.type.Server_DH_inner_data({
buffer: answer
buffer: decryptedDHParams
}).deserialize();
if (logger.isDebugEnabled()) logger.debug('serverDHInnerData = %s obtained in %sms', JSON.stringify(serverDHInnerData), duration);
if (logger.isDebugEnabled()) {
logger.debug('serverDHInnerData = %s obtained in %sms', JSON.stringify(serverDHInnerData), obj.reqDHDuration);
}
// Check if the nonces are consistent
if (serverDHInnerData.nonce != obj.serverDHParams.nonce) {
if (serverDHInnerData.nonce !== obj.serverDHParams.nonce) {
throw createError('Nonce mismatch %s != %s', obj.serverDHParams.nonce, serverDHInnerData.nonce);
}
if (serverDHInnerData.server_nonce != obj.serverDHParams.server_nonce) {
if (serverDHInnerData.server_nonce !== obj.serverDHParams.server_nonce) {
throw createError('ServerNonce mismatch %s != %s', obj.serverDHParams.server_nonce, serverDHInnerData.server_nonce);
}
// Synch the local time with the server time
mtproto.time.timeSynchronization(serverDHInnerData.server_time * 1000, duration);
mtproto.time.timeSynchronization(serverDHInnerData.server_time * 1000, obj.reqDHDuration);
obj.serverDHInnerData = serverDHInnerData;
return obj;
}
Expand All @@ -230,13 +266,17 @@ TelegramLink.prototype.authorization = function (callback) {
// Create the client DH inner data
function createClientDHInnerData(obj) {
var retryCount = 0;
if (logger.isDebugEnabled()) logger.debug('Start calculating g_b');
if (logger.isDebugEnabled()) {
logger.debug('Start calculating g_b');
}
// Calculate g_b
var g = obj.serverDHInnerData.g;
var b = utility.createNonce(256);
var dhPrime = obj.serverDHInnerData.dh_prime;
var gb = utility.modPow(g, b, dhPrime);
if (logger.isDebugEnabled()) logger.debug('g_b(%s) = %s', gb.length, gb.toString('hex'));
if (logger.isDebugEnabled()) {
logger.debug('g_b(%s) = %s', gb.length, gb.toString('hex'));
}
// Create client DH inner data
obj.clientDHInnerData = new mtproto.type.Client_DH_inner_data({props: {
nonce: obj.resPQ.nonce,
Expand All @@ -251,16 +291,19 @@ TelegramLink.prototype.authorization = function (callback) {
function encryptClientDHInnerDataWithAES(obj) {
var hash = utility.createSHA1Hash(obj.clientDHInnerData);
var dataWithHash = Buffer.concat([hash, obj.clientDHInnerData]);
if (logger.isDebugEnabled()) logger.debug('Data to be encrypted contains: ' +
'hash(%s), clientDHInnerData(%s), total length %s',
hash.length, obj.clientDHInnerData.length, dataWithHash.length);
if (logger.isDebugEnabled()) {
logger.debug('Data to be encrypted contains: hash(%s), clientDHInnerData(%s), total length %s',
hash.length, obj.clientDHInnerData.length, dataWithHash.length);
}
obj.encryptClientDHInnerData = security.cipher.aesEncrypt(
dataWithHash,
obj.aes.key,
obj.aes.iv
);
if (logger.isDebugEnabled()) logger.debug('encryptClientDHInnerData(%s) = %s',
obj.encryptClientDHInnerData.length, obj.encryptClientDHInnerData.toString('hex'));
if (logger.isDebugEnabled()) {
logger.debug('encryptClientDHInnerData(%s) = %s',
obj.encryptClientDHInnerData.length, obj.encryptClientDHInnerData.toString('hex'));
}
return obj;
}

Expand All @@ -278,16 +321,18 @@ TelegramLink.prototype.authorization = function (callback) {
logger.error(ex);
if (callback) callback(ex);
} else {
if (setClientDHParamsAnswer.typeName == 'mtproto.type.Dh_gen_ok') {
if (logger.isDebugEnabled()) logger.debug('\'Dh_gen_ok\' received from Telegram.');
if (setClientDHParamsAnswer.typeName === 'mtproto.type.Dh_gen_ok') {
if (logger.isDebugEnabled()) {
logger.debug('\'Dh_gen_ok\' received from Telegram.');
}
obj.setClientDHParamsAnswer = setClientDHParamsAnswer;
callback(null, obj, duration);
} else if (setClientDHParamsAnswer.typeName == 'mtproto.type.Dh_gen_retry') {
} else if (setClientDHParamsAnswer.typeName === 'mtproto.type.Dh_gen_retry') {
logger.warn('\'Dh_gen_retry\' received from Telegram!');
callback(createError(JSON.stringify(serverDHParams), 'EDHPARAMRETRY'));
} else if (setClientDHParamsAnswer.typeName == 'mtproto.type.Dh_gen_fail') {
callback(createError(JSON.stringify(setClientDHParamsAnswer), 'EDHPARAMRETRY'));
} else if (setClientDHParamsAnswer.typeName === 'mtproto.type.Dh_gen_fail') {
logger.warn('\'Dh_gen_fail\' received from Telegram!');
callback(createError(JSON.stringify(serverDHParams), 'EDHPARAMFAIL'));
callback(createError(JSON.stringify(setClientDHParamsAnswer), 'EDHPARAMFAIL'));
} else {
var msg = 'Unknown error received from Telegram!';
logger.error(msg);
Expand Down

0 comments on commit bab1af0

Please sign in to comment.