There are a number of ways to hash messages. If you are content with a SHA-256 hash, then, there’s a really simple way to do what you want. It uses some of the capability that was recently added to the message template in Apigee Edge.
Review:
a Message Template is a string that is used in various places in Apigee Edge policies. As one example, if you use AssignMessage to set a specific payload, then the contents of the Payload element in that policy is treated as a message template. At runtime, Apigee Edge replaces all references to variables, with the values of those variables. Supposing the context variable “bar” holds the value “abc123”, in that case a string like
" foo {bar}"
..when evaluated as a Message Template, results in “foo abc123”.
OK, now recently several cool enhancements have appeared relating to Message Templates.
- there’s an expanded set of “functions” you can refer to within Message Templates
- You can use AssignMessage/AssignVariable to assign a variable via a message template.
One of the functions that has been added is sha256Hex(var). This produces the hex-encoding of the sha256 hash for the named context variable. Suppose the variable “bar” holds the value “abc”. Then this message template:
{sha256Hex(bar)}
…evaluates to the value “ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad”
Therefore, in order to compute the hash, and inject it as a header, you could use a single assignmessage policy like this:
<AssignMessage name='AM-1'>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<!-- specify the jsonpath as a string -->
<AssignVariable>
<Name>json_path_1</Name>
<Value>$.MessageContent</Value>
</AssignVariable>
<!-- Step 2: extract the specific string value via JSONpath -->
<AssignVariable>
<Name>extracted_content</Name>
<Template>{jsonPath(json_path_1,request.content)}</Template>
</AssignVariable>
<!-- Step 3: inject a header containing the hash -->
<Set>
<Headers>
<Header name='content-hash'>{sha256Hex(extracted_content)}</Header>
</Headers>
</set>
</AssignMessage>
What remains is to configure the backend system to compute the same hash and compare.
This all works.
But… you may want to rethink your protocol. if an attacker was able to modify the JSON payload while the message is in transit, the attacker will also be able to modify the hash header to match. Passing the unsecured hash code … doesn’t increase security. It makes the hacker’s job slightly more difficult, but … it adds no appreciable security.
The only way to avoid such a pitfall is to use a keyed message authentication code, aka an HMAC. Or sign the content (the hash or the header or etc) in some other way.
And to compute that you would need a Java callout or a JWT policy, or similar.