init
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
function ChatOmemoStorage() {
|
||||
this.jid = USER_JID;
|
||||
}
|
||||
|
||||
ChatOmemoStorage.prototype = {
|
||||
Direction: {
|
||||
SENDING: 1,
|
||||
RECEIVING: 2,
|
||||
},
|
||||
|
||||
// Storage is versionned to ensure a proper reset when changes are made
|
||||
storageVersion: '2',
|
||||
|
||||
// Generic methods
|
||||
put: function (key, value) {
|
||||
if (key === undefined || value === undefined || key === null || value === null)
|
||||
throw new Error("Tried to store undefined/null");
|
||||
|
||||
return localStorage.setObject(this.storageVersion + '.' + key, value);
|
||||
},
|
||||
get: function (key, defaultValue) {
|
||||
if (key === null || key === undefined)
|
||||
throw new Error("Tried to get value for undefined/null key");
|
||||
if (this.storageVersion + '.' + key in localStorage) {
|
||||
return localStorage.getObject(this.storageVersion + '.' + key);
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
},
|
||||
remove: function (key) {
|
||||
if (key === null || key === undefined)
|
||||
throw new Error("Tried to remove value for undefined/null key");
|
||||
|
||||
localStorage.removeItem(this.storageVersion + '.' + key);
|
||||
},
|
||||
filter: function (search) {
|
||||
return Object.keys(localStorage).filter(key => key.startsWith(this.storageVersion + '.' + this.jid + search));
|
||||
},
|
||||
|
||||
// OMEMO specific methods
|
||||
setIdentityKeyPair: function(identityKeyPair) {
|
||||
return Promise.resolve(this.put(this.jid + '.identityKey', {
|
||||
'privKey': MovimUtils.arrayBufferToBase64(identityKeyPair.privKey),
|
||||
'pubKey': MovimUtils.arrayBufferToBase64(identityKeyPair.pubKey)
|
||||
}));
|
||||
},
|
||||
getIdentityKeyPair: function () {
|
||||
identityKeyPair = this.get(this.jid + '.identityKey');
|
||||
|
||||
if (!identityKeyPair) return Promise.reject();
|
||||
|
||||
return Promise.resolve({
|
||||
'privKey': MovimUtils.base64ToArrayBuffer(identityKeyPair.privKey),
|
||||
'pubKey': MovimUtils.base64ToArrayBuffer(identityKeyPair.pubKey)
|
||||
});
|
||||
},
|
||||
|
||||
setLocalRegistrationId: function (registrationId) {
|
||||
return Promise.resolve(this.put(this.jid + '.registrationId', registrationId));
|
||||
},
|
||||
getLocalRegistrationId: function () {
|
||||
return Promise.resolve(this.get(this.jid + '.registrationId'));
|
||||
},
|
||||
|
||||
isTrustedIdentity: function (identifier, identityKey, direction) {
|
||||
if (identifier === null || identifier === undefined) {
|
||||
throw new Error("tried to check identity key for undefined/null key");
|
||||
}
|
||||
if (!(identityKey instanceof ArrayBuffer)) {
|
||||
throw new Error("Expected identityKey to be an ArrayBuffer");
|
||||
}
|
||||
var trusted = this.get(this.jid + '.identityKey' + identifier);
|
||||
if (trusted === undefined) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
// movim-rs: identities are stored per JID (not per device) so a contact with several
|
||||
// devices would always be rejected. Blind Trust Before Verification, like Conversations:
|
||||
// the fingerprints can still be checked and disabled in the contact drawer.
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
loadIdentityKey: function (identifier) {
|
||||
if (identifier === null || identifier === undefined)
|
||||
throw new Error("Tried to get identity key for undefined/null key");
|
||||
return Promise.resolve(MovimUtils.base64ToArrayBuffer(this.get(this.jid + '.identityKey' + identifier)));
|
||||
},
|
||||
saveIdentity: function (identifier, identityKey) {
|
||||
if (identifier === null || identifier === undefined)
|
||||
throw new Error("Tried to put identity key for undefined/null key");
|
||||
|
||||
var address = new libsignal.SignalProtocolAddress.fromString(identifier);
|
||||
|
||||
var existing = this.get(this.jid + '.identityKey' + address.getName());
|
||||
this.put(this.jid + '.identityKey' + address.getName(), MovimUtils.arrayBufferToBase64(identityKey))
|
||||
|
||||
if (existing && toString(identityKey) !== toString(existing)) {
|
||||
return Promise.resolve(true);
|
||||
} else {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
loadPreKey: function (keyId) {
|
||||
var res = this.get(this.jid + '.25519KeypreKey' + keyId);
|
||||
if (res !== undefined) {
|
||||
res = {
|
||||
pubKey: MovimUtils.base64ToArrayBuffer(res.pubKey),
|
||||
privKey: MovimUtils.base64ToArrayBuffer(res.privKey)
|
||||
};
|
||||
}
|
||||
return Promise.resolve(res);
|
||||
},
|
||||
storePreKey: function (keyId, keyPair) {
|
||||
keyPair.pubKey = MovimUtils.arrayBufferToBase64(keyPair.pubKey);
|
||||
keyPair.privKey = MovimUtils.arrayBufferToBase64(keyPair.privKey);
|
||||
return Promise.resolve(this.put(this.jid + '.25519KeypreKey' + keyId, keyPair));
|
||||
},
|
||||
removePreKey: function (keyId) {
|
||||
return Promise.resolve(this.remove(this.jid + '.25519KeypreKey' + keyId));
|
||||
},
|
||||
|
||||
loadCompleteSignedPreKey: function (keyId) {
|
||||
var res = this.get(this.jid + '.25519KeysignedKey' + keyId);
|
||||
if (res !== undefined) {
|
||||
res = {
|
||||
keyPair: {
|
||||
pubKey: MovimUtils.base64ToArrayBuffer(res.keyPair.pubKey),
|
||||
privKey: MovimUtils.base64ToArrayBuffer(res.keyPair.privKey),
|
||||
},
|
||||
signature: MovimUtils.base64ToArrayBuffer(res.signature),
|
||||
keyId: keyId
|
||||
};
|
||||
}
|
||||
return res;
|
||||
},
|
||||
loadSignedPreKey: function (keyId) {
|
||||
return Promise.resolve(this.loadCompleteSignedPreKey(keyId).keyPair);
|
||||
},
|
||||
storeSignedPreKey: function (keyId, key) {
|
||||
key.keyPair.pubKey = MovimUtils.arrayBufferToBase64(key.keyPair.pubKey);
|
||||
key.keyPair.privKey = MovimUtils.arrayBufferToBase64(key.keyPair.privKey);
|
||||
key.signature = MovimUtils.arrayBufferToBase64(key.signature);
|
||||
return Promise.resolve(this.put(this.jid + '.25519KeysignedKey' + keyId, key));
|
||||
},
|
||||
removeSignedPreKey: function (keyId) {
|
||||
return Promise.resolve(this.remove(this.jid + '.25519KeysignedKey' + keyId));
|
||||
},
|
||||
|
||||
loadSession: function (identifier) {
|
||||
return Promise.resolve(this.get(this.jid + '.session' + identifier));
|
||||
},
|
||||
storeSession: function (identifier, record) {
|
||||
return Promise.resolve(this.put(this.jid + '.session' + identifier, record));
|
||||
},
|
||||
removeSession: function (identifier) {
|
||||
return Promise.resolve(this.remove(this.jid + '.session' + identifier));
|
||||
},
|
||||
removeAllSessions: function () {
|
||||
let filtered = this.filter('.session');
|
||||
|
||||
for (key in filtered) {
|
||||
localStorage.removeItem(filtered[key]);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
getOwnSessions: function () {
|
||||
return this.filter('.session' + this.jid);
|
||||
},
|
||||
getSessions: function (identifier) {
|
||||
return this.filter('.session' + identifier);
|
||||
},
|
||||
getOwnSessionsIds: function () {
|
||||
return this.filter('.session' + this.jid).map(sessionId => sessionId.split('.').pop());
|
||||
},
|
||||
getSessionsIds: function (identifier) {
|
||||
return this.filter('.session' + identifier).map(sessionId => sessionId.split('.').pop());
|
||||
},
|
||||
|
||||
isJidResolved: function (identifier) {
|
||||
return this.hasContactTombstone(identifier) || this.filter('.session' + identifier).length > 0;
|
||||
},
|
||||
|
||||
removeAllSessionsOfJid: function (identifier) {
|
||||
let filtered = this.filter('.session' + identifier);
|
||||
|
||||
for (id in filtered) {
|
||||
localStorage.removeItem(filtered[id]);
|
||||
}
|
||||
|
||||
this.remove(this.jid + '.contact' + identifier);
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
setContactState: function (jid, state) {
|
||||
return Promise.resolve(this.put(this.jid + '.contact' + jid, state));
|
||||
},
|
||||
removeContactState: function (jid) {
|
||||
return Promise.resolve(this.remove(this.jid + '.contact' + jid));
|
||||
},
|
||||
hasContactState: function(jid) {
|
||||
return (this.get(this.jid + '.contact' + jid) !== undefined);
|
||||
},
|
||||
getContactState: function (jid) {
|
||||
let state = Boolean(this.get(this.jid + '.contact' + jid));
|
||||
return Promise.resolve(state);
|
||||
},
|
||||
|
||||
/**
|
||||
* Tombstone to know if a contact doesn't have OMEMO at the moment
|
||||
*/
|
||||
setContactTombstone: function (jid) {
|
||||
return Promise.resolve(this.put(this.jid + '.contact.tombstone' + jid, true));
|
||||
},
|
||||
removeContactTombstone: function (jid) {
|
||||
return Promise.resolve(this.remove(this.jid + '.contact.tombstone' + jid));
|
||||
},
|
||||
hasContactTombstone: function(jid) {
|
||||
return (this.get(this.jid + '.contact.tombstone' + jid) == true);
|
||||
},
|
||||
|
||||
getSessionState: function (identifier) {
|
||||
return this.loadSession(identifier).then(json => {
|
||||
if (json !== undefined) {
|
||||
let session = JSON.parse(json);
|
||||
return (session.state === true || session.state === undefined);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
setSessionState: function (identifier, enabled) {
|
||||
this.loadSession(identifier).then(json => {
|
||||
if (json !== undefined) {
|
||||
let session = JSON.parse(json);
|
||||
session.state = Boolean(enabled);
|
||||
this.storeSession(identifier, JSON.stringify(session));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toString: function(thing) {
|
||||
if (typeof thing == 'string') {
|
||||
return thing;
|
||||
}
|
||||
return new dcodeIO.ByteBuffer.wrap(thing).toString('binary');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user