sign static method
Threshold-sign message with ≥ params.t shares from shares.
M2 beta: uses in-process Mithril coordinator (honest combine model).
Requires mithril_bridge binary and ML-DSA-44 scheme
(mlDsa44ThresholdV1) until native ML-DSA-65 lands.
Implementation
static Future<Uint8List> sign({
required List<MlDsaShare> shares,
required Uint8List message,
Uint8List? context,
String? mithrilBridgePath,
}) async {
assertMlDsaShareSetConsistent(shares);
final params = shares.first.params;
if (params.scheme != SchemeId.mlDsa44ThresholdV1) {
throw SchemeNotImplemented(
'M2 Mithril bridge supports mlDsa44ThresholdV1 only; got ${params.scheme}',
);
}
if (shares.length < params.t) {
throw InsufficientShares(
'Need at least ${params.t} shares, got ${shares.length}',
);
}
final publicKey = MlDsaPublicKey.create(
params: params,
ceremonyId: shares.first.ceremonyId,
publicKeyBytes: await _derivePublicKey(
params: params,
ceremonySeed: shares.first.ceremonySeedBytes(),
mithrilBridgePath: mithrilBridgePath,
),
);
final active = shares
.take(params.t)
.map((s) => s.mithrilPartyId)
.toList()
..sort();
final signature = await mithrilThresholdSign(
t: params.t,
n: params.n,
ceremonySeed: shares.first.ceremonySeedBytes(),
activePartyIdsZeroBased: active,
message: message,
executablePath: mithrilBridgePath,
);
if (!MlDsaThresholdVerifier.verify(
scheme: params.scheme,
publicKey: publicKey.bytes,
message: message,
signature: signature,
context: context,
)) {
throw InvalidPartialSignature('Mithril produced invalid ML-DSA signature');
}
return signature;
}