move textencoder/decoder into platform

This commit is contained in:
Bruno Windels 2021-02-11 17:29:48 +01:00
parent b6938dffdb
commit e49639fda2
6 changed files with 53 additions and 21 deletions

View file

@ -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()) {

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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);

View file

@ -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();

View 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);
}
}