feat: Add managing our own keys
This commit is contained in:
parent
27b1931629
commit
e34e0cc7fb
@ -34,3 +34,8 @@ List<int> generateRandomBytes(int length) {
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Generate a random number between 0 inclusive and 2**32 exclusive (2**32 - 1 inclusive).
|
||||
int generateRandom32BitNumber() {
|
||||
return Random.secure().nextInt(4294967295 /*pow(2, 32) - 1*/);
|
||||
}
|
||||
|
101
lib/src/omemo/device.dart
Normal file
101
lib/src/omemo/device.dart
Normal file
@ -0,0 +1,101 @@
|
||||
import 'dart:convert';
|
||||
import 'package:cryptography/cryptography.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:omemo_dart/src/helpers.dart';
|
||||
import 'package:omemo_dart/src/keys.dart';
|
||||
import 'package:omemo_dart/src/omemo/bundle.dart';
|
||||
import 'package:omemo_dart/src/x3dh/x3dh.dart';
|
||||
|
||||
/// This class represents an OmemoBundle but with all keypairs belonging to the keys
|
||||
@immutable
|
||||
class Device {
|
||||
|
||||
const Device(this.id, this.ik, this.spk, this.spkId, this.spkSignature, this.opks);
|
||||
|
||||
/// Generate a completely new device, i.e. cryptographic identity.
|
||||
static Future<Device> generateNewDevice({ int opkAmount = 100 }) async {
|
||||
final id = generateRandom32BitNumber();
|
||||
final ik = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519);
|
||||
final spk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
||||
final spkId = generateRandom32BitNumber();
|
||||
final signature = await sig(ik, await spk.pk.getBytes());
|
||||
|
||||
final opks = <String, OmemoKeyPair>{};
|
||||
for (var i = 0; i < opkAmount; i++) {
|
||||
opks[i.toString()] = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
||||
}
|
||||
|
||||
return Device(id.toString(), ik, spk, spkId.toString(), signature, opks);
|
||||
}
|
||||
|
||||
/// The device Id
|
||||
final String id;
|
||||
|
||||
/// The identity key
|
||||
final OmemoKeyPair ik;
|
||||
|
||||
/// The signed prekey...
|
||||
final OmemoKeyPair spk;
|
||||
/// ...its Id, ...
|
||||
final String spkId;
|
||||
/// ...and its signature
|
||||
final List<int> spkSignature;
|
||||
|
||||
/// Map of an id to the associated Onetime-Prekey
|
||||
final Map<String, OmemoKeyPair> opks;
|
||||
|
||||
/// This replaces the Onetime-Prekey with id [id] with a completely new one. Returns
|
||||
/// a new Device object that copies over everything but replaces said key.
|
||||
Future<Device> replaceOnetimePrekey(String id) async {
|
||||
final newOpk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
||||
|
||||
return Device(
|
||||
id,
|
||||
ik,
|
||||
spk,
|
||||
spkId,
|
||||
spkSignature,
|
||||
opks.map((keyId, opk) {
|
||||
if (keyId == id) {
|
||||
return MapEntry(id, newOpk);
|
||||
}
|
||||
|
||||
return MapEntry(id, opk);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/// This replaces the Signed-Prekey with a completely new one. Returns a new Device object
|
||||
/// that copies over everything but replaces the Signed-Prekey and its signature.
|
||||
Future<Device> replaceSignedPrekey() async {
|
||||
final newSpk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
|
||||
final newSpkId = generateRandom32BitNumber();
|
||||
final newSignature = await sig(ik, await newSpk.pk.getBytes());
|
||||
|
||||
return Device(
|
||||
id,
|
||||
ik,
|
||||
newSpk,
|
||||
newSpkId.toString(),
|
||||
newSignature,
|
||||
opks,
|
||||
);
|
||||
}
|
||||
|
||||
Future<OmemoBundle> toBundle() async {
|
||||
final encodedOpks = <String, String>{};
|
||||
|
||||
for (final opkKey in opks.keys) {
|
||||
encodedOpks[opkKey] = base64.encode(await opks[opkKey]!.pk.getBytes());
|
||||
}
|
||||
|
||||
return OmemoBundle(
|
||||
id,
|
||||
base64.encode(await spk.pk.getBytes()),
|
||||
spkId,
|
||||
base64.encode(spkSignature),
|
||||
base64.encode(await ik.pk.getBytes()),
|
||||
encodedOpks,
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
import 'package:omemo_dart/src/crypto.dart';
|
||||
import 'package:omemo_dart/src/double_ratchet/double_ratchet.dart';
|
||||
import 'package:omemo_dart/src/helpers.dart';
|
||||
import 'package:omemo_dart/src/omemo/device.dart';
|
||||
import 'package:synchronized/synchronized.dart';
|
||||
|
||||
/// The info used for when encrypting the AES key for the actual payload.
|
||||
@ -21,8 +22,15 @@ class EncryptionResult {
|
||||
|
||||
class OmemoSessionManager {
|
||||
|
||||
OmemoSessionManager() : _ratchetMap = {}, _deviceMap = {}, _lock = Lock();
|
||||
OmemoSessionManager(this.device) : _ratchetMap = {}, _deviceMap = {}, _lock = Lock();
|
||||
|
||||
/// Generate a new cryptographic identity.
|
||||
static Future<OmemoSessionManager> generateNewIdentity({ int opkAmount = 100 }) async {
|
||||
final device = await Device.generateNewDevice(opkAmount: opkAmount);
|
||||
|
||||
return OmemoSessionManager(device);
|
||||
}
|
||||
|
||||
/// Lock for _ratchetMap and _bundleMap
|
||||
final Lock _lock;
|
||||
|
||||
@ -32,6 +40,9 @@ class OmemoSessionManager {
|
||||
/// Mapping of a bare Jid to its Device Ids
|
||||
final Map<String, List<String>> _deviceMap;
|
||||
|
||||
/// Our own keys
|
||||
Device device;
|
||||
|
||||
/// Add a session [ratchet] with the [deviceId] to the internal tracking state.
|
||||
Future<void> addSession(String jid, String deviceId, OmemoDoubleRatchet ratchet) async {
|
||||
await _lock.synchronized(() async {
|
||||
|
Loading…
Reference in New Issue
Block a user