feat: Auto-selfsign and auto-cache when opening ssss keys
This commit is contained in:
parent
fb5a0bc6a2
commit
6c2fc1679a
|
|
@ -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);
|
||||
await handle.unlock(
|
||||
{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);
|
||||
await handle.maybeCacheAll();
|
||||
keyOrPassphrase: keyOrPassphrase,
|
||||
postUnlock: false,
|
||||
);
|
||||
await handle.maybeCacheAll();
|
||||
}
|
||||
final masterPrivateKey =
|
||||
base64.decode(await handle.getStored(EventTypes.CrossSigningMasterKey));
|
||||
final keyObj = olm.PkSigning();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
Loading…
Reference in New Issue