Php encode code vs js

hi all,

here a PHP sample :

$headers = getallheaders();
$body = file_get_contents(‘php://input’);
$signature = rawurlencode(base64_encode(hash_hmac(‘sha256’, $body, ’ xxsecretecesretxx’, true)));
echo $headers[‘webhook-signature’] === $signature) ? ‘ok’ : ‘bad’;

how can i mimic this ?
is there a way to check this on a credential type ?

i try with a crypto node without succes. Even with this : PHP's rawurlencode is not equal to JavaScripts escape! Why? - Stack Overflow

I think that the php
$body = file_get_contents(‘php://input’)
is not equal to
{JSON.stringify($node[“Import”].json[“body”])

any help would be appreciated. Thanks

{
  "nodes": [
    {
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{JSON.stringify($node[\"Import\"].json[\"body\"])}}",
        "secret": "xxxsecretsecretxxx",
        "encoding": "base64"
      },
      "name": "Crypto",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 1,
      "position": [
        740,
        420
      ]
    }
  ],
  "connections": {}
}

Hi @Christel_Doudet, I am afraid I don’t speak PHP, so wouldn’t be able to confirm the exact equivalent of your PHP snippet.

The StackOverflow thread you have linked suggests it might be a charset problem. Could you share some example data you are working with and on which you’re unable to perform the hmac action from your example? Your expression references an Import node, but it’s not clear to me what kind of node this is or what it does.

It would be great if you could also confirm the PHP output for your example data, so people can see the difference.

Edit: If the charset is the problem and your data is simply the response to an HTTP Request, you could try this approach to set the correct encoding:

Hey @Christel_Doudet,

I have managed to get this working, I suspect the issue could be where your php script is doing the rawurlencode() on the base64 encoded result. To get around this I have used encodeURIComponent() in an expression.

So my test is…

<?php
$body = file_get_contents('http://n8n.io');
$signature = rawurlencode(base64_encode(hash_hmac('sha256', $body, 'xxsecretecesretxx', true)));
echo $signature;
?>

This results in an output of 9KHNCAnhV%2FDvk%2BF7xyMskfe0kH%2FfIBqb0ND3MB02SSE%3D in the sample workflow I am putting that value in a set node to compare it later.

I then use the HTTP Request node to the the n8n website data (this is the php_get_contents() part not exactly the same as file but the theory is the same).

I then have the Crypto mode configured for HMAC, SHA256 and BASE64 Encoding, I then use the same secret. This results in an output of 9KHNCAnhV/Dvk+F7xyMskfe0kH/fIBqb0ND3MB02SSE=.

In the If statement I am then using the output from the first set node and comparing it to the encodeURIComponent() value of the output of the Crypto node.

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "url": "http://n8n.io",
        "responseFormat": "string",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        520,
        300
      ]
    },
    {
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{$node[\"HTTP Request\"].json[\"data\"]}}",
        "secret": "xxsecretecesretxx",
        "encoding": "base64"
      },
      "name": "Crypto",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 1,
      "position": [
        660,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "sigFromPHP",
              "value": "9KHNCAnhV%2FDvk%2BF7xyMskfe0kH%2FfIBqb0ND3MB02SSE%3D"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        380,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Set\"].json[\"sigFromPHP\"]}}",
              "value2": "={{encodeURIComponent($json[\"data\"])}}"
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        800,
        300
      ]
    },
    {
      "parameters": {},
      "name": "We have a match",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        980,
        280
      ]
    },
    {
      "parameters": {},
      "name": "No match",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        980,
        460
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Crypto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Crypto": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "We have a match",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No match",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Hopefully this helps with what you are trying to do.

2 Likes