createKey method
Creates a new secret storage key, optional encrypts it with passphrase
and stores it in the user's accountData
.
Implementation
Future<OpenSSSS> createKey([String? passphrase]) async {
Uint8List privateKey;
final content = SecretStorageKeyContent();
if (passphrase != null) {
// we need to derive the key off of the passphrase
content.passphrase = PassphraseInfo(
iterations: pbkdf2DefaultIterations,
salt: base64.encode(uc.secureRandomBytes(pbkdf2SaltLength)),
algorithm: AlgorithmTypes.pbkdf2,
bits: ssssKeyLength * 8,
);
privateKey = await Future.value(
client.nativeImplementations.keyFromPassphrase(
KeyFromPassphraseArgs(
passphrase: passphrase,
info: content.passphrase!,
),
),
).timeout(Duration(seconds: 10));
} else {
// we need to just generate a new key from scratch
privateKey = Uint8List.fromList(uc.secureRandomBytes(ssssKeyLength));
}
// now that we have the private key, let's create the iv and mac
final encrypted = await encryptAes(zeroStr, privateKey, '');
content.iv = encrypted.iv;
content.mac = encrypted.mac;
content.algorithm = AlgorithmTypes.secretStorageV1AesHmcSha2;
const keyidByteLength = 24;
// make sure we generate a unique key id
final keyId = () sync* {
for (;;) {
yield base64.encode(uc.secureRandomBytes(keyidByteLength));
}
}()
.firstWhere((keyId) => getKey(keyId) == null);
final accountDataTypeKeyId = EventTypes.secretStorageKey(keyId);
// noooow we set the account data
await client.setAccountData(
client.userID!,
accountDataTypeKeyId,
content.toJson(),
);
while (!client.accountData.containsKey(accountDataTypeKeyId)) {
Logs().v('Waiting accountData to have $accountDataTypeKeyId');
await client.oneShotSync();
}
final key = open(keyId);
await key.setPrivateKey(privateKey);
return key;
}