From bab1af0817d6e0d0eb634b2dc9d7b123920f9ed6 Mon Sep 17 00:00:00 2001 From: Enrico Stara Date: Fri, 28 Nov 2014 17:51:53 +0100 Subject: [PATCH] Increase the code quality --- lib/telegram.link.js | 125 +++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/lib/telegram.link.js b/lib/telegram.link.js index 1bbc0f0..6824f34 100644 --- a/lib/telegram.link.js +++ b/lib/telegram.link.js @@ -63,6 +63,7 @@ TelegramLink.prototype.authorization = function (callback) { encryptPQInnerDataWithRSA, requestDHParams, decryptDHParams, + deserializeDHInnerData, createClientDHInnerData, encryptClientDHInnerDataWithAES, setClientDHParams @@ -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')); @@ -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], @@ -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; @@ -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; @@ -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 { @@ -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; } @@ -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, @@ -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; } @@ -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);