verifyEnvelopeSignature method

Future<void> verifyEnvelopeSignature(
  1. SignedEnvelope envelope, {
  2. required String signerAtSign,
  3. String? signerEnrollmentId,
  4. EnvelopeType expecting = EnvelopeType.app,
})

Verify an envelope created by wrapAndSign or wrapAndSignAndJsonEncode.

The signature is verified against the APKAM public signing key which the signer's enrollment (the enrollmentId field of the envelope) has published at public:_apsk.<enrollmentId>.a.__e<signerAtSign>. Only the owning enrollment may write to that location, so a valid signature proves the envelope was created by a client of that (approved) enrollment.

Throws an Exception on failed validation. A cached key that fails is dropped and fetched once more first, since the enrollment may have rotated away from it.

signerEnrollmentId overrides the envelope's own enrollmentId claim as the address to fetch _apsk from. Supply it whenever something outside the envelope already establishes whose it is, which is also the only way to verify an envelope that carries no claim of its own — a key package signed before its enrollment had an id, say.

expecting is what the caller is verifying; an envelope signed for anything else is refused before its signature is checked. It defaults to EnvelopeType.app to pair with wrapAndSign's default.

Implementation

Future<void> verifyEnvelopeSignature(
  SignedEnvelope envelope, {
  required String signerAtSign,
  String? signerEnrollmentId,
  EnvelopeType expecting = EnvelopeType.app,
}) async {
  final String? id = signerEnrollmentId ?? envelope.signerEnrollmentId;
  if (id == null) {
    throw AtSigningVerificationException(
        'Cannot verify an envelope that names no enrollment and was given '
        'none: there is no _apsk to check the signature against');
  }

  final atSign = signerAtSign.toAtsign();
  final cached = lookupPubKey(atSign, id);
  if (cached != null) {
    try {
      await verifyEnvelope(envelope,
          signerPublicKey: cached, expecting: expecting);
      return;
    } on AtSigningVerificationException {
      pubKeyCache.remove(_cacheKey(atSign, id));
    }
  }

  final pk = await getApkamPublicKey(atSign, id);
  try {
    await verifyEnvelope(envelope, signerPublicKey: pk, expecting: expecting);
  } on AtSigningVerificationException catch (e) {
    throw AtSigningVerificationException(
        'Signature verification failed using public key for '
        '$signerAtSign enrollment $id : $pk — ${e.message}');
  }
}