Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New HMAC built-in functions #1740

Closed
jshaw86 opened this issue Sep 10, 2019 · 4 comments · Fixed by #4100
Closed

New HMAC built-in functions #1740

jshaw86 opened this issue Sep 10, 2019 · 4 comments · Fixed by #4100

Comments

@jshaw86
Copy link

jshaw86 commented Sep 10, 2019

I'm interfacing with a 3rd party service that doesn't send JWT tokens and would like todo a custom HMAC calculation on a header. Looking at the docs I only see token signing/verification in the context of JWT. Does Rego only support HMAC with JWT tokens or am I missing something?

Follow up, if not can the hmac be abstracted away from JWT or was there a specific design decision in only supporting JWT? I didn't see much in #1174 describing the decisions.

@tsandall
Copy link
Member

tsandall commented Sep 10, 2019

OPA only exposes built-in functions for verifying signatures on JWTs today. Adding support for verifying arbitrary HMACs would be relatively easy (since we can just wrap the Go standard library). Assuming symmetric keys are being used could do something like this in policy:

allow {
  valid_hmac
}

valid_hmac {
  hmac.verify_sha256(input.headers["message"]. input.headers["signature"], "secret")
}

The built-in function would return true if the HMAC was valid and be false/undefined otherwise.

If you're embedding OPA as a library or building it yourself you can add custom built-in functions. Here's an example: https://www.openpolicyagent.org/docs/latest/plugins/#built-in-functions. Note, we don't recommend using Go shared libraries/plugins anymore.

@jshaw86 jshaw86 changed the title Question: Is it possible to validate non-jwt tokens? Feature Request: HMAC arbitrary request signature Sep 10, 2019
@jshaw86
Copy link
Author

jshaw86 commented Sep 10, 2019

@tsandall yea thats basically the idea. I'm not sure what best practice would be in terms of abstraction for rego built-ins. The only major difference between that function prototype and what I was thinking was the first param. Rather than accepting a single header to compare against it would accept a hash of params then they would be sorted and built into a string. The caller then could apply params from a single or combination of sources in the signature calculation

Sample in java

  public Boolean verify_sha256(Map<String, String> params, String signature, String secret) {
    try {
      StringBuilder builder = new StringBuilder();
      if (params != null) {
        List<String> sortedKeys = new ArrayList<>(params.keySet());
        Collections.sort(sortedKeys);

        for (String key : sortedKeys) {
          builder.append(key);

          String value = params.get(key);
          builder.append(value == null ? "" : value);
        }
      }
      Mac mac = Mac.getInstance(HMAC);
      mac.init(secret);

      byte[] rawHmac = mac.doFinal(builder.toString().getBytes(StandardCharsets.UTF_8));
      return DatatypeConverter.printBase64Binary(rawHmac) == signature;

    } catch (Exception e) {
      return null;
    }
  }

I guess I'm not sure how clunky it would be in the calling env in rego to build the param hash, or if that is pretty easy.

@tsandall
Copy link
Member

If you wanted to construct the message from multiple fields in the input you could do that as well. For example, with the above signature:

hmac.verify_sha256(concat("", [input.headers["abc"], input.headers["def"]]), input.headers["signature"], "secret")

If you wanted to sort a set of values you can do that too:

> sort([3,2,1])
[1,2,3]

@jshaw86
Copy link
Author

jshaw86 commented Oct 10, 2019

Thanks. I might be able to get to this around the start of the year.

@johanfylling johanfylling self-assigned this Dec 2, 2021
@tsandall tsandall changed the title Feature Request: HMAC arbitrary request signature New HMAC built-in functions Dec 8, 2021
johanfylling added a commit to johanfylling/opa that referenced this issue Dec 9, 2021
Add crypto.hmac.* built-in functions for the MD5, SHA-1, SHA-256 and SHA-512 hashing algorithms.

Add documentation for how to contribute new built-in functions.

Fixes: open-policy-agent#1740
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
johanfylling added a commit that referenced this issue Dec 9, 2021
Add crypto.hmac.* built-in functions for the MD5, SHA-1, SHA-256 and SHA-512 hashing algorithms.

Add documentation for how to contribute new built-in functions.

Fixes: #1740
Signed-off-by: Johan Fylling <johan.dev@fylling.se>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants