mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 03:25:12 +01:00
WIP2
This commit is contained in:
parent
25aac4b7c0
commit
8cf7a1b161
@ -777,13 +777,15 @@ export class Session {
|
|||||||
txn.accountData.set(event);
|
txn.accountData.set(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changes.accountData = accountData.events;
|
if (this._secretStorage) {
|
||||||
|
changes.secretStorageChanges = await this._secretStorage.writeSync(accountData.events, txn, log);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
afterSync({syncInfo, e2eeAccountChanges, accountData}) {
|
afterSync({syncInfo, e2eeAccountChanges, secretStorageChanges}) {
|
||||||
if (syncInfo) {
|
if (syncInfo) {
|
||||||
// sync transaction succeeded, modify object state now
|
// sync transaction succeeded, modify object state now
|
||||||
this._syncInfo = syncInfo;
|
this._syncInfo = syncInfo;
|
||||||
@ -791,8 +793,8 @@ export class Session {
|
|||||||
if (this._e2eeAccount) {
|
if (this._e2eeAccount) {
|
||||||
this._e2eeAccount.afterSync(e2eeAccountChanges);
|
this._e2eeAccount.afterSync(e2eeAccountChanges);
|
||||||
}
|
}
|
||||||
if (accountData && this._secretStorage) {
|
if (secretStorageChanges && this._secretStorage) {
|
||||||
this._secretStorage.afterSync(accountData);
|
this._secretStorage.afterSync(secretStorageChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import type {Key} from "./common";
|
import {BaseObservableValue, RetainedObservableValue} from "../../observable/value";
|
||||||
|
import {KeyType} from "./index";
|
||||||
|
import {keyFromPassphrase} from "./passphrase";
|
||||||
|
import {keyFromRecoveryKey} from "./recoveryKey";
|
||||||
|
import type {Key, KeyDescription} from "./common";
|
||||||
import type {Platform} from "../../platform/web/Platform.js";
|
import type {Platform} from "../../platform/web/Platform.js";
|
||||||
import type {Transaction} from "../storage/idb/Transaction";
|
import type {Transaction} from "../storage/idb/Transaction";
|
||||||
import type {Storage} from "../storage/idb/Storage";
|
import type {Storage} from "../storage/idb/Storage";
|
||||||
@ -37,11 +41,25 @@ class DecryptionError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AccountData = {type: string, content: Record<string, any>};
|
||||||
|
|
||||||
|
type KeyCredentials = {
|
||||||
|
type: KeyType,
|
||||||
|
credential: string
|
||||||
|
}
|
||||||
|
|
||||||
export class SecretStorage {
|
export class SecretStorage {
|
||||||
private readonly _key: Key;
|
// we know the id but don't have the description yet
|
||||||
|
private _keyId?: string;
|
||||||
|
// we have the description but not the credentials yet
|
||||||
|
private _keyDescription?: KeyDescription;
|
||||||
|
// we have the credentials but not the id or description yet
|
||||||
|
private _keyCredentials?: KeyCredentials;
|
||||||
|
// we have everything to compose a valid key
|
||||||
|
private _key?: Key;
|
||||||
private readonly _platform: Platform;
|
private readonly _platform: Platform;
|
||||||
private readonly _storage: Storage;
|
private readonly _storage: Storage;
|
||||||
private observedSecrets
|
private observedSecrets: Map<string, RetainedObservableValue<string | undefined>>;
|
||||||
|
|
||||||
constructor({key, platform, storage}: {key: Key, platform: Platform, storage: Storage}) {
|
constructor({key, platform, storage}: {key: Key, platform: Platform, storage: Storage}) {
|
||||||
this._key = key;
|
this._key = key;
|
||||||
@ -49,12 +67,60 @@ export class SecretStorage {
|
|||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
afterSync(accountData: ReadonlyArray<{type: string, content: Record<string, any>}>): void {
|
load() {
|
||||||
for(const event of accountData) {
|
// read key
|
||||||
if (type === )
|
}
|
||||||
|
|
||||||
|
async setKey(type: KeyType, credential: string) {
|
||||||
|
const credentials: KeyCredentials = {type, credential};
|
||||||
|
this._keyCredentials = credentials;
|
||||||
|
this.updateKey(this._keyDescription, this._keyCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setKeyWithDehydratedDeviceKey() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateKey(keyDescription: KeyDescription | undefined, credentials: KeyCredentials | undefined, txn: Transaction) {
|
||||||
|
if (keyDescription && credentials) {
|
||||||
|
if (credentials.type === KeyType.Passphrase) {
|
||||||
|
this._key = await keyFromPassphrase(keyDescription, credentials.credential, this._platform);
|
||||||
|
} else if (credentials.type === KeyType.RecoveryKey) {
|
||||||
|
this._key = await keyFromRecoveryKey(keyDescription, credentials.credential, this._olm, this._platform);
|
||||||
|
}
|
||||||
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private update(keyDescription: KeyDescription, credentials: KeyCredentials) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSync(accountData: ReadonlyArray<AccountData>, txn: Transaction, log: ILogItem): Promise<void> {
|
||||||
|
|
||||||
|
const newDefaultKey = accountData.find(e => e.type === "m.secret_storage.default_key");
|
||||||
|
const keyId: string | undefined = newDefaultKey ? newDefaultKey.content?.key : this._keyId;
|
||||||
|
const keyEventType = keyId ? `m.secret_storage.key.${keyId}` : undefined;
|
||||||
|
let newKey = keyEventType ? accountData.find(e => e.type === keyEventType) : undefined;
|
||||||
|
if (newDefaultKey && keyEventType && !newKey) {
|
||||||
|
newKey = await txn.accountData.get(keyEventType);
|
||||||
|
}
|
||||||
|
if (newKey) {
|
||||||
|
this.setKeyDescription()
|
||||||
|
}
|
||||||
|
const keyChanged = !!newDefaultKey || !!newKey;
|
||||||
|
if (keyChanged) {
|
||||||
|
// update all values
|
||||||
|
} else {
|
||||||
|
for(const event of accountData) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterSync(): void {
|
||||||
|
}
|
||||||
|
|
||||||
/** this method will auto-commit any indexeddb transaction because of its use of the webcrypto api */
|
/** this method will auto-commit any indexeddb transaction because of its use of the webcrypto api */
|
||||||
async hasValidKeyForAnyAccountData() {
|
async hasValidKeyForAnyAccountData() {
|
||||||
const txn = await this._storage.readTxn([
|
const txn = await this._storage.readTxn([
|
||||||
|
@ -30,8 +30,8 @@ const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`;
|
|||||||
const BACKUPVERSION_KEY = `${SESSION_E2EE_KEY_PREFIX}keyBackupVersion`;
|
const BACKUPVERSION_KEY = `${SESSION_E2EE_KEY_PREFIX}keyBackupVersion`;
|
||||||
|
|
||||||
export enum KeyType {
|
export enum KeyType {
|
||||||
"RecoveryKey",
|
RecoveryKey,
|
||||||
"Passphrase"
|
Passphrase
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readDefaultKeyDescription(storage: Storage): Promise<KeyDescription | undefined> {
|
async function readDefaultKeyDescription(storage: Storage): Promise<KeyDescription | undefined> {
|
||||||
|
@ -27,7 +27,7 @@ const DEFAULT_BITSIZE = 256;
|
|||||||
* @param {Platform} platform
|
* @param {Platform} platform
|
||||||
* @return {Key}
|
* @return {Key}
|
||||||
*/
|
*/
|
||||||
export async function keyFromPassphrase(keyDescription: KeyDescription, passphrase: string, platform: Platform): Promise<Key> {
|
export async function keyFromPassphrase(passphrase: string, platform: Platform): Promise<Key> {
|
||||||
const {passphraseParams} = keyDescription;
|
const {passphraseParams} = keyDescription;
|
||||||
if (!passphraseParams) {
|
if (!passphraseParams) {
|
||||||
throw new Error("not a passphrase key");
|
throw new Error("not a passphrase key");
|
||||||
|
Loading…
Reference in New Issue
Block a user