Move registrationId from session record to session state

This was mostly used internally by SessionRecord to flag the lack of an
open session, but that can be replaced with an actual check for an open
session.
This commit is contained in:
lilia 2016-09-19 16:43:59 -07:00
parent ffd60c7d94
commit ddba403ef5
5 changed files with 73 additions and 74 deletions

View File

@ -35554,37 +35554,28 @@ Internal.SessionRecord = function() {
return JSON.stringify(ensureStringed(thing)); //TODO: jquery???
}
var SessionRecord = function(registrationId) {
var SessionRecord = function() {
this._sessions = {};
this.registrationId = registrationId;
if (this.registrationId === undefined || typeof this.registrationId !== 'number') {
this.registrationId = null;
}
};
SessionRecord.deserialize = function(serialized) {
var data = JSON.parse(serialized);
var record = new SessionRecord(data.registrationId);
var record = new SessionRecord();
record._sessions = data.sessions;
if (record._sessions === undefined || record._sessions === null || typeof record._sessions !== "object" || Array.isArray(record._sessions)) {
throw new Error("Error deserializing SessionRecord");
}
if (record.registrationId === undefined) {
throw new Error("Error deserializing SessionRecord");
}
return record;
};
SessionRecord.prototype = {
serialize: function() {
return jsonThing({
sessions : this._sessions,
registrationId : this.registrationId
sessions : this._sessions
});
},
haveOpenSession: function() {
return this.registrationId !== null;
return this.getOpenSession() !== undefined;
},
getSessionByBaseKey: function(baseKey) {
@ -35643,7 +35634,7 @@ Internal.SessionRecord = function() {
}
}
},
updateSessionState: function(session, registrationId) {
updateSessionState: function(session) {
var sessions = this._sessions;
this.removeOldChains(session);
@ -35652,19 +35643,6 @@ Internal.SessionRecord = function() {
this.removeOldSessions();
var openSessionRemaining = false;
for (var key in sessions) {
if (sessions[key].indexInfo.closed == -1) {
openSessionRemaining = true;
}
}
if (!openSessionRemaining) { // Used as a flag to get new pre keys for the next session
this.registrationId = null;
} else if (this.registrationId === null && registrationId !== undefined) {
this.registrationId = registrationId;
} else if (this.registrationId === null) {
throw new Error("Had open sessions on a record that had no registrationId set");
}
},
getSessions: function() {
// return an array of sessions ordered by time closed,
@ -35818,7 +35796,7 @@ SessionBuilder.prototype = {
}).then(function(baseKey) {
var devicePreKey = (device.preKey.publicKey);
return this.initSession(true, baseKey, undefined, device.identityKey,
devicePreKey, device.signedPreKey.publicKey
devicePreKey, device.signedPreKey.publicKey, device.registrationId
).then(function(session) {
session.pendingPreKey = {
preKeyId : device.preKey.keyId,
@ -35834,7 +35812,7 @@ SessionBuilder.prototype = {
if (serialized !== undefined) {
record = Internal.SessionRecord.deserialize(serialized);
} else {
record = new Internal.SessionRecord(device.registrationId);
record = new Internal.SessionRecord();
}
record.archiveCurrentState();
@ -35892,7 +35870,7 @@ SessionBuilder.prototype = {
}
return this.initSession(false, preKeyPair, signedPreKeyPair,
message.identityKey.toArrayBuffer(),
message.baseKey.toArrayBuffer(), undefined
message.baseKey.toArrayBuffer(), undefined, message.registrationId
).then(function(new_session) {
// Note that the session is not actually saved until the very
// end of decryptWhisperMessage ... to ensure that the sender
@ -35906,7 +35884,7 @@ SessionBuilder.prototype = {
},
initSession: function(isInitiator, ourEphemeralKey, ourSignedKey,
theirIdentityPubKey, theirEphemeralPubKey,
theirSignedPubKey) {
theirSignedPubKey, registrationId) {
return this.storage.getIdentityKeyPair().then(function(ourIdentityKey) {
if (isInitiator) {
if (ourSignedKey !== undefined) {
@ -35956,6 +35934,7 @@ SessionBuilder.prototype = {
return Internal.HKDF(sharedSecret.buffer, new ArrayBuffer(32), "WhisperText");
}).then(function(masterKey) {
var session = {
registrationId: registrationId,
currentRatchet: {
rootKey : masterKey[0],
lastRemoteEphemeralKey : theirSignedPubKey,
@ -36114,14 +36093,14 @@ SessionCipher.prototype = {
return {
type : 3,
body : result,
registrationId : record.registrationId
registrationId : session.registrationId
};
} else {
return {
type : 1,
body : util.toString(message),
registrationId : record.registrationId
registrationId : session.registrationId
};
}
});
@ -36346,7 +36325,11 @@ SessionCipher.prototype = {
if (record === undefined) {
return undefined;
}
return record.registrationId;
var openSession = record.getOpenSession();
if (openSession === undefined) {
return null;
}
return openSession.registrationId;
});
}.bind(this));
},

View File

@ -23,7 +23,7 @@ SessionBuilder.prototype = {
}).then(function(baseKey) {
var devicePreKey = (device.preKey.publicKey);
return this.initSession(true, baseKey, undefined, device.identityKey,
devicePreKey, device.signedPreKey.publicKey
devicePreKey, device.signedPreKey.publicKey, device.registrationId
).then(function(session) {
session.pendingPreKey = {
preKeyId : device.preKey.keyId,
@ -39,7 +39,7 @@ SessionBuilder.prototype = {
if (serialized !== undefined) {
record = Internal.SessionRecord.deserialize(serialized);
} else {
record = new Internal.SessionRecord(device.registrationId);
record = new Internal.SessionRecord();
}
record.archiveCurrentState();
@ -97,7 +97,7 @@ SessionBuilder.prototype = {
}
return this.initSession(false, preKeyPair, signedPreKeyPair,
message.identityKey.toArrayBuffer(),
message.baseKey.toArrayBuffer(), undefined
message.baseKey.toArrayBuffer(), undefined, message.registrationId
).then(function(new_session) {
// Note that the session is not actually saved until the very
// end of decryptWhisperMessage ... to ensure that the sender
@ -111,7 +111,7 @@ SessionBuilder.prototype = {
},
initSession: function(isInitiator, ourEphemeralKey, ourSignedKey,
theirIdentityPubKey, theirEphemeralPubKey,
theirSignedPubKey) {
theirSignedPubKey, registrationId) {
return this.storage.getIdentityKeyPair().then(function(ourIdentityKey) {
if (isInitiator) {
if (ourSignedKey !== undefined) {
@ -161,6 +161,7 @@ SessionBuilder.prototype = {
return Internal.HKDF(sharedSecret.buffer, new ArrayBuffer(32), "WhisperText");
}).then(function(masterKey) {
var session = {
registrationId: registrationId,
currentRatchet: {
rootKey : masterKey[0],
lastRemoteEphemeralKey : theirSignedPubKey,

View File

@ -97,14 +97,14 @@ SessionCipher.prototype = {
return {
type : 3,
body : result,
registrationId : record.registrationId
registrationId : session.registrationId
};
} else {
return {
type : 1,
body : util.toString(message),
registrationId : record.registrationId
registrationId : session.registrationId
};
}
});
@ -329,7 +329,11 @@ SessionCipher.prototype = {
if (record === undefined) {
return undefined;
}
return record.registrationId;
var openSession = record.getOpenSession();
if (openSession === undefined) {
return null;
}
return openSession.registrationId;
});
}.bind(this));
},

View File

@ -55,37 +55,28 @@ Internal.SessionRecord = function() {
return JSON.stringify(ensureStringed(thing)); //TODO: jquery???
}
var SessionRecord = function(registrationId) {
var SessionRecord = function() {
this._sessions = {};
this.registrationId = registrationId;
if (this.registrationId === undefined || typeof this.registrationId !== 'number') {
this.registrationId = null;
}
};
SessionRecord.deserialize = function(serialized) {
var data = JSON.parse(serialized);
var record = new SessionRecord(data.registrationId);
var record = new SessionRecord();
record._sessions = data.sessions;
if (record._sessions === undefined || record._sessions === null || typeof record._sessions !== "object" || Array.isArray(record._sessions)) {
throw new Error("Error deserializing SessionRecord");
}
if (record.registrationId === undefined) {
throw new Error("Error deserializing SessionRecord");
}
return record;
};
SessionRecord.prototype = {
serialize: function() {
return jsonThing({
sessions : this._sessions,
registrationId : this.registrationId
sessions : this._sessions
});
},
haveOpenSession: function() {
return this.registrationId !== null;
return this.getOpenSession() !== undefined;
},
getSessionByBaseKey: function(baseKey) {
@ -144,7 +135,7 @@ Internal.SessionRecord = function() {
}
}
},
updateSessionState: function(session, registrationId) {
updateSessionState: function(session) {
var sessions = this._sessions;
this.removeOldChains(session);
@ -153,19 +144,6 @@ Internal.SessionRecord = function() {
this.removeOldSessions();
var openSessionRemaining = false;
for (var key in sessions) {
if (sessions[key].indexInfo.closed == -1) {
openSessionRemaining = true;
}
}
if (!openSessionRemaining) { // Used as a flag to get new pre keys for the next session
this.registrationId = null;
} else if (this.registrationId === null && registrationId !== undefined) {
this.registrationId = registrationId;
} else if (this.registrationId === null) {
throw new Error("Had open sessions on a record that had no registrationId set");
}
},
getSessions: function() {
// return an array of sessions ordered by time closed,

View File

@ -4,14 +4,31 @@
'use strict';
describe('SessionCipher', function() {
describe('getRemoteRegistrationId', function() {
var store = new SignalProtocolStore();
var registrationId = 1337;
var address = new libsignal.SignalProtocolAddress('foo', 1);
var sessionCipher = new libsignal.SessionCipher(store, address.toString());
describe('when a record exists', function() {
describe('when an open record exists', function() {
before(function(done) {
var record = new Internal.SessionRecord(registrationId);
var session = {
registrationId: registrationId,
currentRatchet: {
rootKey : new ArrayBuffer(32),
lastRemoteEphemeralKey : new ArrayBuffer(32),
previousCounter : 0
},
indexInfo: {
baseKey : new ArrayBuffer(32),
baseKeyType : Internal.BaseKeyType.OURS,
remoteIdentityKey : new ArrayBuffer(32),
closed : -1
},
oldRatchetList: []
};
record.updateSessionState(session);
store.storeSession(address.toString(), record.serialize()).then(done);
});
it('returns a valid registrationId', function(done) {
@ -34,23 +51,39 @@ describe('SessionCipher', function() {
var store = new SignalProtocolStore();
var address = new libsignal.SignalProtocolAddress('foo', 1);
var sessionCipher = new libsignal.SessionCipher(store, address.toString());
describe('registrationId is valid', function() {
describe('open session exists', function() {
before(function(done) {
var record = new Internal.SessionRecord( 1);
var record = new Internal.SessionRecord();
var session = {
registrationId: 1337,
currentRatchet: {
rootKey : new ArrayBuffer(32),
lastRemoteEphemeralKey : new ArrayBuffer(32),
previousCounter : 0
},
indexInfo: {
baseKey : new ArrayBuffer(32),
baseKeyType : Internal.BaseKeyType.OURS,
remoteIdentityKey : new ArrayBuffer(32),
closed : -1
},
oldRatchetList: []
};
record.updateSessionState(session);
store.storeSession(address.toString(), record.serialize()).then(done);
});
it('returns true for a session with a valid registrationId', function(done) {
it('returns true', function(done) {
sessionCipher.hasOpenSession(address.toString()).then(function(value) {
assert.isTrue(value);
}).then(done,done);
});
});
describe('registrationId is null', function() {
describe('no open session exists', function() {
before(function(done) {
var record = new Internal.SessionRecord();
store.storeSession(address.toString(), record.serialize()).then(done);
});
it('returns false for a session with a null registrationId', function(done) {
it('returns false', function(done) {
sessionCipher.hasOpenSession(address.toString()).then(function(value) {
assert.isFalse(value);
}).then(done,done);