Cannot verify Defender Relayer signatures on OZs ECDSA Solidity library

We're using Relayer (Defender 2) to sign authentication messages to guard access to a certain function. According to https://docs.openzeppelin.com/defender/v2/manage/relayers#signing it creates non-deterministic signatures. We can confirm that: with every client call we receive different signature bytes but on the frontend they all are recoverable to the correct relay address (0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE) using viem's recoverMessageAddress and recoverAddress. When trying to verify them using the OZ ECDSA contract library, we however cannot recover the relay / signer address correctly. Using the latest version of @openzeppelin/defender-sdk / 1.11.0, using Cancun VM.

Client:

const { Defender } = require('@openzeppelin/defender-sdk')
const { hashMessage, recoverMessageAddress, recoverAddress } = require('viem')
require('dotenv-flow').config({
  default_node_env: 'development'
})

const main = async () => {
  const creds = {
    relayerApiKey: process.env.DEFENDER_RELAY_API_KEY,
    relayerApiSecret: process.env.DEFENDER_RELAY_SECRET_KEY
  }
  const client = new Defender(creds)
  const validUntil = new Date(Date.now() + 120 * 1000).toISOString()
  const signer = await client.relaySigner.getSigner(
    client.relaySigner.getProvider(),
    { speed: 'fast', validUntil }
  )

  const plainMessage = 'hello world'
  const signature = await signer.signMessage(plainMessage)
  console.log('signature', signature)

  const address = await recoverMessageAddress({
    message: plainMessage,
    signature: signature
  })
  console.log('recovered address 1', address)

  console.log(
    'recovered address 2',
    await recoverAddress({
      hash: hashMessage(plainMessage),
      signature
    })
  )
}

;(async () => {
  await main()
})()

Output:

$ yarn ts-node cli/testRelayer.ts
signature 0x5d52923f24f9edb9e0ac19160183c0731b77795b7c4acaa0e81587aa3e64e6e710c0df2567f3396e5be7dd3816b2de9d69270cfb7d34e58c8b5d20711a19498f1b
recovered address 1 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE
recovered address 2 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE
$ yarn ts-node cli/testRelayer.ts
signature 0x5e0c589c5790b134223a866bd253ff73ad6a00482d96234d3b72c0cb64eccbc63cede8769090ed91d62983af41bbd2d200359469b2d77bd0096587a297554cef1b
recovered address 1 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE
recovered address 2 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE
$ yarn ts-node cli/testRelayer.ts
signature 0x36efe70274ca04d2590bfebfe63e2c0099a60c51009bfcfdf63e9734d30de91e3fd861722c7f0d1e727d01fc9eb1e50663ba879c61b08a7ee07ba51f7b635b9d1c
recovered address 1 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE
recovered address 2 0xd7B298c9fB0377124d01D4E826d9D5beFB7CD6FE

Contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

import {SignatureChecker} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/utils/cryptography/SignatureChecker.sol";
import {ECDSA} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/utils/cryptography/ECDSA.sol";
import {MessageHashUtils} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol";

contract SignedMintAuthorizer {
    function authorizeMint(string memory authMessage, bytes memory signature) external pure returns (address) {
        bytes32 signedHash = MessageHashUtils.toEthSignedMessageHash(keccak256(bytes(authMessage)));
        (address signer,ECDSA.RecoverError err,bytes32 any) = ECDSA.tryRecover(signedHash, signature);
        return signer;
    }
}

Call Results:

{
	"string authMessage": "hello world",
	"bytes signature": "0x5e0c589c5790b134223a866bd253ff73ad6a00482d96234d3b72c0cb64eccbc63cede8769090ed91d62983af41bbd2d200359469b2d77bd0096587a297554cef1b"
}
->
{
	"0": "address: 0xC548fB656F3CbB7cCd8FAe6335B30883d1EB4008"
}
---
{
	"string authMessage": "hello world",
	"bytes signature": "0x36efe70274ca04d2590bfebfe63e2c0099a60c51009bfcfdf63e9734d30de91e3fd861722c7f0d1e727d01fc9eb1e50663ba879c61b08a7ee07ba51f7b635b9d1c"
}
-> 
{
	"0": "address: 0x00FB5b0EEE636D748C8B23CdD23C4b54348f0135"
}

2 Likes