forked from mystiq/hydrogen-web
move textencoder/decoder into platform
This commit is contained in:
parent
b6938dffdb
commit
e49639fda2
6 changed files with 53 additions and 21 deletions
|
@ -184,7 +184,7 @@ export class Session {
|
|||
if (this._sessionBackup) {
|
||||
return false;
|
||||
}
|
||||
const key = await ssssKeyFromCredential(type, credential, this._storage, this._platform.crypto, this._olm);
|
||||
const key = await ssssKeyFromCredential(type, credential, this._storage, this._platform, this._olm);
|
||||
// and create session backup, which needs to read from accountData
|
||||
const readTxn = this._storage.readTxn([
|
||||
this._storage.storeNames.accountData,
|
||||
|
@ -206,7 +206,7 @@ export class Session {
|
|||
}
|
||||
|
||||
async _createSessionBackup(ssssKey, txn) {
|
||||
const secretStorage = new SecretStorage({key: ssssKey, crypto: this._platform.crypto});
|
||||
const secretStorage = new SecretStorage({key: ssssKey, platform: this._platform});
|
||||
this._sessionBackup = await SessionBackup.fromSecretStorage({olm: this._olm, secretStorage, hsApi: this._hsApi, txn});
|
||||
if (this._sessionBackup) {
|
||||
for (const room of this._rooms.values()) {
|
||||
|
|
|
@ -17,9 +17,9 @@ limitations under the License.
|
|||
import base64 from "../../../lib/base64-arraybuffer/index.js";
|
||||
|
||||
export class SecretStorage {
|
||||
constructor({key, crypto}) {
|
||||
constructor({key, platform}) {
|
||||
this._key = key;
|
||||
this._crypto = crypto;
|
||||
this._platform = platform;
|
||||
}
|
||||
|
||||
async readSecret(name, txn) {
|
||||
|
@ -40,14 +40,11 @@ export class SecretStorage {
|
|||
}
|
||||
|
||||
async _decryptAESSecret(type, encryptedData) {
|
||||
// TODO: we should we move this to platform specific code
|
||||
const textEncoder = new TextEncoder();
|
||||
const textDecoder = new TextDecoder();
|
||||
// now derive the aes and mac key from the 4s key
|
||||
const hkdfKey = await this._crypto.derive.hkdf(
|
||||
const hkdfKey = await this._platform.crypto.derive.hkdf(
|
||||
this._key.binaryKey,
|
||||
new Uint8Array(8).buffer, //zero salt
|
||||
textEncoder.encode(type), // info
|
||||
this._platform.utf8.encode(type), // info
|
||||
"SHA-256",
|
||||
512 // 512 bits or 64 bytes
|
||||
);
|
||||
|
@ -56,7 +53,7 @@ export class SecretStorage {
|
|||
|
||||
const ciphertextBytes = base64.decode(encryptedData.ciphertext);
|
||||
|
||||
const isVerified = await this._crypto.hmac.verify(
|
||||
const isVerified = await this._platform.crypto.hmac.verify(
|
||||
hmacKey, base64.decode(encryptedData.mac),
|
||||
ciphertextBytes, "SHA-256");
|
||||
|
||||
|
@ -64,12 +61,12 @@ export class SecretStorage {
|
|||
throw new Error("Bad MAC");
|
||||
}
|
||||
|
||||
const plaintextBytes = await this._crypto.aes.decryptCTR({
|
||||
const plaintextBytes = await this._platform.crypto.aes.decryptCTR({
|
||||
key: aesKey,
|
||||
iv: base64.decode(encryptedData.iv),
|
||||
data: ciphertextBytes
|
||||
});
|
||||
|
||||
return textDecoder.decode(plaintextBytes);
|
||||
return this._platform.utf8.decode(plaintextBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,14 +47,14 @@ export async function readKey(txn) {
|
|||
return new Key(new KeyDescription(keyData.id, keyAccountData), keyData.binaryKey);
|
||||
}
|
||||
|
||||
export async function keyFromCredential(type, credential, storage, crypto, olm) {
|
||||
export async function keyFromCredential(type, credential, storage, platform, olm) {
|
||||
const keyDescription = await readDefaultKeyDescription(storage);
|
||||
if (!keyDescription) {
|
||||
throw new Error("Could not find a default secret storage key in account data");
|
||||
}
|
||||
let key;
|
||||
if (type === "phrase") {
|
||||
key = await keyFromPassphrase(keyDescription, credential, crypto);
|
||||
key = await keyFromPassphrase(keyDescription, credential, platform);
|
||||
} else if (type === "key") {
|
||||
key = keyFromRecoveryKey(olm, keyDescription, credential);
|
||||
} else {
|
||||
|
|
|
@ -22,10 +22,10 @@ const DEFAULT_BITSIZE = 256;
|
|||
/**
|
||||
* @param {KeyDescription} keyDescription
|
||||
* @param {string} passphrase
|
||||
* @param {Crypto} crypto
|
||||
* @param {Platform} platform
|
||||
* @return {Key}
|
||||
*/
|
||||
export async function keyFromPassphrase(keyDescription, passphrase, crypto) {
|
||||
export async function keyFromPassphrase(keyDescription, passphrase, platform) {
|
||||
const {passphraseParams} = keyDescription;
|
||||
if (!passphraseParams) {
|
||||
throw new Error("not a passphrase key");
|
||||
|
@ -33,13 +33,11 @@ export async function keyFromPassphrase(keyDescription, passphrase, crypto) {
|
|||
if (passphraseParams.algorithm !== "m.pbkdf2") {
|
||||
throw new Error(`Unsupported passphrase algorithm: ${passphraseParams.algorithm}`);
|
||||
}
|
||||
// TODO: we should we move this to platform specific code
|
||||
const textEncoder = new TextEncoder();
|
||||
const keyBits = await crypto.derive.pbkdf2(
|
||||
textEncoder.encode(passphrase),
|
||||
const keyBits = await platform.crypto.derive.pbkdf2(
|
||||
platform.utf8.encode(passphrase),
|
||||
passphraseParams.iterations || DEFAULT_ITERATIONS,
|
||||
// salt is just a random string, not encoded in any way
|
||||
textEncoder.encode(passphraseParams.salt),
|
||||
platform.utf8.encode(passphraseParams.salt),
|
||||
"SHA-512",
|
||||
passphraseParams.bits || DEFAULT_BITSIZE);
|
||||
return new Key(keyDescription, keyBits);
|
||||
|
|
|
@ -19,6 +19,7 @@ import {xhrRequest} from "./dom/request/xhr.js";
|
|||
import {StorageFactory} from "../../matrix/storage/idb/StorageFactory.js";
|
||||
import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionInfoStorage.js";
|
||||
import {SettingsStorage} from "./dom/SettingsStorage.js";
|
||||
import {UTF8} from "./dom/UTF8.js";
|
||||
import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js";
|
||||
import {RootView} from "./ui/RootView.js";
|
||||
import {Clock} from "./dom/Clock.js";
|
||||
|
@ -83,6 +84,7 @@ export class Platform {
|
|||
constructor(container, paths, cryptoExtras = null) {
|
||||
this._paths = paths;
|
||||
this._container = container;
|
||||
this.utf8 = new UTF8();
|
||||
this.clock = new Clock();
|
||||
this.history = new History();
|
||||
this.onlineStatus = new OnlineStatus();
|
||||
|
|
35
src/platform/web/dom/UTF8.js
Normal file
35
src/platform/web/dom/UTF8.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
export class UTF8 {
|
||||
constructor() {
|
||||
this._encoder = null;
|
||||
this._decoder = null;
|
||||
}
|
||||
|
||||
encode(str) {
|
||||
if (!this._encoder) {
|
||||
this._encoder = new TextEncoder();
|
||||
}
|
||||
return this._encoder.encode(str);
|
||||
}
|
||||
|
||||
decode(buffer) {
|
||||
if (!this._decoder) {
|
||||
this._decoder = new TextDecoder();
|
||||
}
|
||||
return this._decoder.decode(buffer);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue