verifyEip712ProofDetailed function

Eip712VerificationResult verifyEip712ProofDetailed(
  1. CrossmintVerifiableCredential credential
)

Verifies an EIP-712 typed data signature on a Verifiable Credential.

Recovers the signer address from the proof signature and compares it with the issuer DID address (did:{method}:{address}).

Currently performs only structural validation: the returned result is either Eip712VerificationInvalid (with a specific reason) or Eip712VerificationStructuralOnly when the envelope parses. Full cryptographic verification requires the issuer's EIP-712 domain config, which is not yet surfaced in the credential model.

Implementation

Eip712VerificationResult verifyEip712ProofDetailed(
  CrossmintVerifiableCredential credential,
) {
  final proof = credential.proof;
  if (proof.isEmpty) {
    return const Eip712VerificationInvalid('empty proof');
  }

  final Object? proofValue = proof['proofValue'] ?? proof['jws'];
  if (proofValue is! String || proofValue.isEmpty) {
    return const Eip712VerificationInvalid('missing proofValue');
  }

  final issuerAddress = _extractAddressFromDid(credential.issuer.id);
  if (issuerAddress == null) {
    return const Eip712VerificationInvalid('malformed issuer DID');
  }

  // The proof contains a hex-encoded secp256k1 signature (r + s + v).
  final sigBytes = _hexToBytes(proofValue);
  if (sigBytes == null || sigBytes.length != 65) {
    return const Eip712VerificationInvalid('invalid signature bytes');
  }

  // The official SDK uses ethers.verifyTypedData() which requires the full
  // EIP-712 domain and types. Those aren't currently part of the credential
  // model, so we stop at structural validation and signal that explicitly
  // via Eip712VerificationStructuralOnly.
  return const Eip712VerificationStructuralOnly();
}