sign method

Future<Map<String, Object?>> sign({
  1. required Map<String, Object?> body,
  2. required List<int> seed,
  3. required String signerId,
  4. required String keyId,
})

Implementation

Future<Map<String, Object?>> sign({
  required Map<String, Object?> body,
  required List<int> seed,
  required String signerId,
  required String keyId,
}) async {
  if (seed.length != 32) {
    throw ArgumentError.value(
      seed.length,
      'seed',
      'Ed25519 seed must be 32 bytes',
    );
  }
  const requiredBody = [
    'workspace',
    'repositoryState',
    'engineVersion',
    'lockDigest',
    'policyHash',
    'evidenceRequirementsHash',
    'assurance',
    'evidenceDigests',
    'previousRecord',
  ];
  for (final key in requiredBody) {
    if (!body.containsKey(key) ||
        ((key.endsWith('Hash') || key == 'lockDigest') &&
            body[key] is! String)) {
      throw FormatException('Release body is missing $key');
    }
  }
  final unsigned = <String, Object?>{
    'kind': 'zuke.behavioral-assurance-release',
    'signer': {'signerId': signerId, 'keyId': keyId, 'algorithm': 'Ed25519'},
    'body': body,
  };
  final bytes = releaseSigningPayload(unsigned);
  final digest = sha256.convert(bytes).toString();
  final keyPair = await algorithm.newKeyPairFromSeed(seed);
  final signature = await algorithm.sign(bytes, keyPair: keyPair);
  return {
    ...unsigned,
    'recordDigest': digest,
    'signature': base64Encode(signature.bytes),
  };
}