You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Support default keys
This commit is contained in:
@@ -110,6 +110,53 @@ describe("Secrets", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should refuse to encrypt with zero keys", async function() {
|
||||||
|
const alice = await makeTestClient(
|
||||||
|
{userId: "@alice:example.com", deviceId: "Osborne2"},
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await alice.storeSecret("foo", "bar", []);
|
||||||
|
expect(true).toBeFalsy();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should encrypt with default key if keys is null", async function() {
|
||||||
|
const alice = await makeTestClient(
|
||||||
|
{userId: "@alice:example.com", deviceId: "Osborne2"},
|
||||||
|
);
|
||||||
|
alice.setAccountData = async function(eventType, contents, callback) {
|
||||||
|
alice.store.storeAccountDataEvents([
|
||||||
|
new MatrixEvent({
|
||||||
|
type: eventType,
|
||||||
|
content: contents,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const newKeyId = await alice.addSecretKey(
|
||||||
|
'm.secret_storage.v1.curve25519-aes-sha2',
|
||||||
|
);
|
||||||
|
await alice.setDefaultKeyId(newKeyId);
|
||||||
|
await alice.storeSecret("foo", "bar");
|
||||||
|
|
||||||
|
const accountData = alice.getAccountData('foo');
|
||||||
|
expect(accountData.getContent().encrypted).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should refuse to encrypt if no keys given and no default key", async function() {
|
||||||
|
const alice = await makeTestClient(
|
||||||
|
{userId: "@alice:example.com", deviceId: "Osborne2"},
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await alice.storeSecret("foo", "bar");
|
||||||
|
expect(true).toBeFalsy();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("should request secrets from other clients", async function() {
|
it("should request secrets from other clients", async function() {
|
||||||
const [osborne2, vax] = await makeTestClients(
|
const [osborne2, vax] = await makeTestClients(
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1113,6 +1113,8 @@ wrapCryptoFuncs(MatrixClient, [
|
|||||||
"getSecret",
|
"getSecret",
|
||||||
"isSecretStored",
|
"isSecretStored",
|
||||||
"requestSecret",
|
"requestSecret",
|
||||||
|
"getDefaultKeyId",
|
||||||
|
"setDefaultKeyId",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,6 +34,19 @@ export default class SecretStorage extends EventEmitter {
|
|||||||
this._cryptoCallbacks = cryptoCallbacks;
|
this._cryptoCallbacks = cryptoCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDefaultKeyId() {
|
||||||
|
const defaultKeyEvent = this._baseApis.getAccountData('m.secret_storage.default_key');
|
||||||
|
if (!defaultKeyEvent) return null;
|
||||||
|
return defaultKeyEvent.getContent().key;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultKeyId(keyId) {
|
||||||
|
return this._baseApis.setAccountData(
|
||||||
|
'm.secret_storage.default_key',
|
||||||
|
{ key: keyId },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a key for encrypting secrets.
|
* Add a key for encrypting secrets.
|
||||||
*
|
*
|
||||||
@@ -49,6 +62,8 @@ export default class SecretStorage extends EventEmitter {
|
|||||||
async addKey(algorithm, opts, keyID) {
|
async addKey(algorithm, opts, keyID) {
|
||||||
const keyData = {algorithm};
|
const keyData = {algorithm};
|
||||||
|
|
||||||
|
if (!opts) opts = {};
|
||||||
|
|
||||||
if (opts.name) {
|
if (opts.name) {
|
||||||
keyData.name = opts.name;
|
keyData.name = opts.name;
|
||||||
}
|
}
|
||||||
@@ -86,7 +101,7 @@ export default class SecretStorage extends EventEmitter {
|
|||||||
if (!keyID) {
|
if (!keyID) {
|
||||||
do {
|
do {
|
||||||
keyID = randomString(32);
|
keyID = randomString(32);
|
||||||
} while (!this._baseApis.getAccountData(`m.secret_storage.key.${keyID}`));
|
} while (this._baseApis.getAccountData(`m.secret_storage.key.${keyID}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: sign keyData?
|
// FIXME: sign keyData?
|
||||||
@@ -106,10 +121,23 @@ export default class SecretStorage extends EventEmitter {
|
|||||||
* @param {string} name The name of the secret
|
* @param {string} name The name of the secret
|
||||||
* @param {string} secret The secret contents.
|
* @param {string} secret The secret contents.
|
||||||
* @param {Array} keys The IDs of the keys to use to encrypt the secret
|
* @param {Array} keys The IDs of the keys to use to encrypt the secret
|
||||||
|
* or null/undefined to use the default key.
|
||||||
*/
|
*/
|
||||||
async store(name, secret, keys) {
|
async store(name, secret, keys) {
|
||||||
const encrypted = {};
|
const encrypted = {};
|
||||||
|
|
||||||
|
if (!keys) {
|
||||||
|
const defaultKeyId = this.getDefaultKeyId();
|
||||||
|
if (!defaultKeyId) {
|
||||||
|
throw new Error("No keys specified and no default key present");
|
||||||
|
}
|
||||||
|
keys = [defaultKeyId];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys.length === 0) {
|
||||||
|
throw new Error("Zero keys given to encrypt with!");
|
||||||
|
}
|
||||||
|
|
||||||
for (const keyName of keys) {
|
for (const keyName of keys) {
|
||||||
// get key information from key storage
|
// get key information from key storage
|
||||||
const keyInfo = this._baseApis.getAccountData(
|
const keyInfo = this._baseApis.getAccountData(
|
||||||
|
|||||||
@@ -236,6 +236,14 @@ Crypto.prototype.requestSecret = function(name, devices) {
|
|||||||
return this._secretStorage.request(name, devices);
|
return this._secretStorage.request(name, devices);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Crypto.prototype.getDefaultKeyId = function() {
|
||||||
|
return this._secretStorage.getDefaultKeyId();
|
||||||
|
};
|
||||||
|
|
||||||
|
Crypto.prototype.setDefaultKeyId = function(k) {
|
||||||
|
return this._secretStorage.setDefaultKeyId(k);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that a given private key matches a given public key
|
* Checks that a given private key matches a given public key
|
||||||
* This can be used by the getCrossSigningKey callback to verify that the
|
* This can be used by the getCrossSigningKey callback to verify that the
|
||||||
|
|||||||
Reference in New Issue
Block a user