Don't promote archived sessions, more logging on error

This commit is contained in:
Scott Nonnenberg 2020-12-09 14:05:11 -08:00 committed by GitHub
parent 1098e59f87
commit 5369950c1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 48 deletions

View file

@ -24840,7 +24840,14 @@ SessionCipher.prototype = {
if (sessionList.length === 0) {
var error = errors[0];
if (!error) {
error = new Error('decryptWithSessionList: list is empty, but no errors in array');
error = new Error('decryptWithSessionList: list is empty, but no errors in array');
}
if (errors.length > 1) {
errors.forEach((item, index) => {
var stackString = error && error.stack ? error.stack : error;
var extraString = error && error.extra ? JSON.stringify(error.extra) : '';
console.error(`decryptWithSessionList: Error at index ${index}: ${extraString} ${stackString}`);
});
}
return Promise.reject(error);
}
@ -24865,11 +24872,17 @@ SessionCipher.prototype = {
if (!record) {
throw new Error("No record for device " + address);
}
// Only used for printing out debug information when errors happen
var messageProto = buffer.slice(1, buffer.byteLength - 8);
var message = Internal.protobuf.WhisperMessage.decode(messageProto);
var byEphemeralKey = record.getSessionByRemoteEphemeralKey(util.toString(message.ephemeralKey));
var errors = [];
return this.decryptWithSessionList(buffer, record.getSessions(), errors).then(function(result) {
return this.getRecord(address).then(function(record) {
var openSession = record.getOpenSession();
if (!openSession || result.session.indexInfo.baseKey !== openSession.indexInfo.baseKey) {
if (!openSession) {
record.archiveCurrentState();
record.promoteState(result.session);
}
@ -24889,7 +24902,36 @@ SessionCipher.prototype = {
});
}.bind(this));
}.bind(this));
}.bind(this));
}.bind(this)).catch(function(error) {
try {
error.extra = error.extra || {};
error.extra.foundMatchingSession = Boolean(byEphemeralKey);
if (byEphemeralKey) {
var receivingChainInfo = {};
var entries = Object.entries(byEphemeralKey);
entries.forEach(([key, item]) => {
if (item && item.chainType === Internal.ChainType.RECEIVING && item.chainKey) {
var hexKey = dcodeIO.ByteBuffer.wrap(key, 'binary').toString('hex');
receivingChainInfo[hexKey] = {
counter: item.chainKey.counter,
key: item.chainKey.key ? dcodeIO.ByteBuffer.wrap(item.chainKey.key, 'binary').toString('hex') : null,
};
}
});
error.extra.receivingChainInfo = receivingChainInfo;
}
} catch (innerError) {
console.error(
'decryptWhisperMessage: Problem collecting extra information:',
innerError && innerError.stack ? innerError.stack : innerError
);
}
throw error;
});
}.bind(this));
}.bind(this));
},
@ -24946,7 +24988,12 @@ SessionCipher.prototype = {
var remoteEphemeralKey = message.ephemeralKey.toArrayBuffer();
if (session === undefined) {
return Promise.reject(new Error("No session found to decrypt message from " + this.remoteAddress.toString()));
var error = new Error('No session found to decrypt message from ' + this.remoteAddress.toString());
error.extra = {
messageCounter: message.counter,
ratchetKey: message.ephemeralKey.toString('hex'),
};
return Promise.reject(error);
}
if (session.indexInfo.closed != -1) {
console.log('decrypting message for closed session');
@ -24961,7 +25008,7 @@ SessionCipher.prototype = {
return this.fillMessageKeys(chain, message.counter).then(function() {
var messageKey = chain.messageKeys[message.counter];
if (messageKey === undefined) {
var e = new Error("Message key not found. The counter was repeated or the key was not filled.");
var e = new Error(`Message key not found. Counter ${message.counter} was repeated or the key was not filled.`);
e.name = 'MessageCounterError';
throw e;
}
@ -24979,24 +25026,19 @@ SessionCipher.prototype = {
macInput[33*2] = (3 << 4) | 3;
macInput.set(new Uint8Array(messageProto), 33*2 + 1);
return Internal.verifyMAC(macInput.buffer, keys[1], mac, 8).catch(function(error) {
function logArrayBuffer(name, arrayBuffer) {
console.log('Bad MAC: ' + name + ' - truthy: ' + Boolean(arrayBuffer) +', length: ' + (arrayBuffer ? arrayBuffer.byteLength : 'NaN'));
}
logArrayBuffer('ourPubKey', ourPubKey);
logArrayBuffer('remoteIdentityKey', remoteIdentityKey);
logArrayBuffer('messageProto', messageProto);
logArrayBuffer('mac', mac);
throw error;
});
return Internal.verifyMAC(macInput.buffer, keys[1], mac, 8);
}.bind(this)).then(function() {
return Internal.crypto.decrypt(keys[0], message.ciphertext.toArrayBuffer(), keys[2].slice(0, 16));
});
}.bind(this)).then(function(plaintext) {
delete session.pendingPreKey;
return plaintext;
}).catch(function(error) {
error.extra = {
messageCounter: message.counter,
ratchetKey: message.ephemeralKey.toString('hex'),
};
throw error;
});
},
fillMessageKeys: function(chain, counter) {