extract verifying a signed object from the device tracker

This commit is contained in:
Bruno Windels 2020-09-02 17:37:48 +02:00
parent bd64aaf029
commit 0545c1f0c5
2 changed files with 28 additions and 22 deletions

View file

@ -14,13 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import anotherjson from "../../../lib/another-json/index.js"; import {verifyEd25519Signature, SIGNATURE_ALGORITHM} from "./common.js";
const TRACKING_STATUS_OUTDATED = 0; const TRACKING_STATUS_OUTDATED = 0;
const TRACKING_STATUS_UPTODATE = 1; const TRACKING_STATUS_UPTODATE = 1;
const DEVICE_KEYS_SIGNATURE_ALGORITHM = "ed25519";
// map 1 device from /keys/query response to DeviceIdentity // map 1 device from /keys/query response to DeviceIdentity
function deviceKeysAsDeviceIdentity(deviceSection) { function deviceKeysAsDeviceIdentity(deviceSection) {
const deviceId = deviceSection["device_id"]; const deviceId = deviceSection["device_id"];
@ -200,7 +198,7 @@ export class DeviceTracker {
if (deviceIdOnKeys !== deviceId) { if (deviceIdOnKeys !== deviceId) {
return false; return false;
} }
return this._verifyUserDeviceKeys(deviceKeys); return this._hasValidSignature(deviceKeys);
}); });
const verifiedKeys = verifiedEntries.map(([, deviceKeys]) => deviceKeys); const verifiedKeys = verifiedEntries.map(([, deviceKeys]) => deviceKeys);
return {userId, verifiedKeys}; return {userId, verifiedKeys};
@ -208,26 +206,11 @@ export class DeviceTracker {
return verifiedKeys; return verifiedKeys;
} }
_verifyUserDeviceKeys(deviceSection) { _hasValidSignature(deviceSection) {
const deviceId = deviceSection["device_id"]; const deviceId = deviceSection["device_id"];
const userId = deviceSection["user_id"]; const userId = deviceSection["user_id"];
const clone = Object.assign({}, deviceSection); const ed25519Key = deviceSection?.keys?.[`${SIGNATURE_ALGORITHM}:${deviceId}`];
delete clone.unsigned; return verifyEd25519Signature(this._olmUtil, userId, deviceId, ed25519Key, deviceSection);
delete clone.signatures;
const canonicalJson = anotherjson.stringify(clone);
const key = deviceSection?.keys?.[`${DEVICE_KEYS_SIGNATURE_ALGORITHM}:${deviceId}`];
const signature = deviceSection?.signatures?.[userId]?.[`${DEVICE_KEYS_SIGNATURE_ALGORITHM}:${deviceId}`];
try {
if (!signature) {
throw new Error("no signature");
}
// throws when signature is invalid
this._olmUtil.ed25519_verify(key, canonicalJson, signature);
return true;
} catch (err) {
console.warn("Invalid device signature, ignoring device.", key, canonicalJson, signature, err);
return false;
}
} }
/** /**

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import anotherjson from "../../../lib/another-json/index.js";
// use common prefix so it's easy to clear properties that are not e2ee related during session clear // use common prefix so it's easy to clear properties that are not e2ee related during session clear
export const SESSION_KEY_PREFIX = "e2ee:"; export const SESSION_KEY_PREFIX = "e2ee:";
export const OLM_ALGORITHM = "m.olm.v1.curve25519-aes-sha2"; export const OLM_ALGORITHM = "m.olm.v1.curve25519-aes-sha2";
@ -27,3 +29,24 @@ export class DecryptionError extends Error {
this.details = detailsObj; this.details = detailsObj;
} }
} }
export const SIGNATURE_ALGORITHM = "ed25519";
export function verifyEd25519Signature(olmUtil, userId, deviceOrKeyId, ed25519Key, value) {
const clone = Object.assign({}, value);
delete clone.unsigned;
delete clone.signatures;
const canonicalJson = anotherjson.stringify(clone);
const signature = value?.signatures?.[userId]?.[`${SIGNATURE_ALGORITHM}:${deviceOrKeyId}`];
try {
if (!signature) {
throw new Error("no signature");
}
// throws when signature is invalid
this._olmUtil.ed25519_verify(ed25519Key, canonicalJson, signature);
return true;
} catch (err) {
console.warn("Invalid signature, ignoring.", ed25519Key, canonicalJson, signature, err);
return false;
}
}