Merge branch 'soru/auto-selfsign' into 'main'

feat: Auto-selfsign and auto-cache when opening ssss keys

See merge request famedly/famedlysdk!650
This commit is contained in:
Krille Fear 2021-02-13 13:59:18 +00:00
commit 1f7e517dbf
3 changed files with 73 additions and 9 deletions

View File

@ -23,6 +23,7 @@ import 'package:olm/olm.dart' as olm;
import '../famedlysdk.dart';
import 'encryption.dart';
import 'ssss.dart';
class CrossSigning {
final Encryption encryption;
@ -71,13 +72,21 @@ class CrossSigning {
}
Future<void> selfSign(
{String passphrase, String recoveryKey, String keyOrPassphrase}) async {
final handle = encryption.ssss.open(EventTypes.CrossSigningMasterKey);
{String passphrase,
String recoveryKey,
String keyOrPassphrase,
OpenSSSS openSsss}) async {
var handle = openSsss;
if (handle == null) {
handle = encryption.ssss.open(EventTypes.CrossSigningMasterKey);
await handle.unlock(
passphrase: passphrase,
recoveryKey: recoveryKey,
keyOrPassphrase: keyOrPassphrase);
keyOrPassphrase: keyOrPassphrase,
postUnlock: false,
);
await handle.maybeCacheAll();
}
final masterPrivateKey =
base64.decode(await handle.getStored(EventTypes.CrossSigningMasterKey));
final keyObj = olm.PkSigning();

View File

@ -29,6 +29,7 @@ import 'package:password_hash/password_hash.dart';
import '../famedlysdk.dart';
import '../src/database/database.dart';
import '../src/utils/run_in_background.dart';
import '../src/utils/run_in_root.dart';
import 'encryption.dart';
const CACHE_TYPES = <String>{
@ -617,20 +618,32 @@ class OpenSSSS {
Uint8List privateKey;
bool get isUnlocked => privateKey != null;
bool get hasPassphrase => keyData.passphrase != null;
String get recoveryKey =>
isUnlocked ? SSSS.encodeRecoveryKey(privateKey) : null;
Future<void> unlock(
{String passphrase, String recoveryKey, String keyOrPassphrase}) async {
{String passphrase,
String recoveryKey,
String keyOrPassphrase,
bool postUnlock = true}) async {
if (keyOrPassphrase != null) {
try {
await unlock(recoveryKey: keyOrPassphrase);
await unlock(recoveryKey: keyOrPassphrase, postUnlock: postUnlock);
} catch (_) {
await unlock(passphrase: keyOrPassphrase);
if (hasPassphrase) {
await unlock(passphrase: keyOrPassphrase, postUnlock: postUnlock);
} else {
rethrow;
}
}
return;
} else if (passphrase != null) {
if (!hasPassphrase) {
throw Exception(
'Tried to unlock with passphrase while key does not have a passphrase');
}
privateKey = await runInBackground(
_keyFromPassphrase,
_KeyFromPassphraseArgs(
@ -647,6 +660,9 @@ class OpenSSSS {
privateKey = null;
throw Exception('Inalid key');
}
if (postUnlock) {
await runInRoot(() => _postUnlock());
}
}
void setPrivateKey(Uint8List key) {
@ -671,6 +687,19 @@ class OpenSSSS {
Future<void> maybeCacheAll() async {
await ssss.maybeCacheAll(keyId, privateKey);
}
Future<void> _postUnlock() async {
// first try to cache all secrets that aren't cached yet
await maybeCacheAll();
// now try to self-sign
if (ssss.encryption.crossSigning.enabled && ssss.client.isUnknownSession) {
try {
await ssss.encryption.crossSigning.selfSign(openSsss: this);
} catch (e, s) {
Logs().e('[SSSS] Failed to self-sign', e, s);
}
}
}
}
class _KeyFromPassphraseArgs {

View File

@ -124,9 +124,10 @@ void main() {
});
test('cache', () async {
await client.encryption.ssss.clearCache();
final handle =
client.encryption.ssss.open(EventTypes.CrossSigningSelfSigning);
await handle.unlock(recoveryKey: SSSS_KEY);
await handle.unlock(recoveryKey: SSSS_KEY, postUnlock: false);
expect(
(await client.encryption.ssss
.getCached(EventTypes.CrossSigningSelfSigning)) !=
@ -155,6 +156,30 @@ void main() {
true);
});
test('postUnlock', () async {
await client.encryption.ssss.clearCache();
client.userDeviceKeys[client.userID].masterKey.setDirectVerified(false);
final handle =
client.encryption.ssss.open(EventTypes.CrossSigningSelfSigning);
await handle.unlock(recoveryKey: SSSS_KEY);
expect(
(await client.encryption.ssss
.getCached(EventTypes.CrossSigningSelfSigning)) !=
null,
true);
expect(
(await client.encryption.ssss
.getCached(EventTypes.CrossSigningUserSigning)) !=
null,
true);
expect(
(await client.encryption.ssss.getCached(EventTypes.MegolmBackup)) !=
null,
true);
expect(
client.userDeviceKeys[client.userID].masterKey.directVerified, true);
});
test('make share requests', () async {
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
@ -245,6 +270,7 @@ void main() {
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
key.setDirectVerified(false);
client.userDeviceKeys[client.userID].masterKey.setDirectVerified(false);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.request',