Skip to main content

Sign and verify requests with HTTP Message Signatures

Introduction

In modern API-driven architectures, ensuring the integrity and authenticity of API requests is crucial to prevent unauthorized access and protect sensitive data. The HTTP Message Signatures plugin for Gate provides a robust solution for signing and verifying API requests using digital signatures. This use case guide will walk you through the process of implementing HTTP Message Signatures in your API requests using the Gate plugin.

The plugin implements HTTP Message Signatures, RFC 9421.

Benefits of HTTP Message Signatures over TLS

While TLS (Transport Layer Security) is crucial for securing data in transit by encrypting the connection, it has some limitations, HTTP Message Signatures complement TLS by addressing its limitations and providing additional security benefits:

  1. End-to-End Data Integrity and Authentication

    • Persistent Integrity: With HTTP Message Signatures, each message or request is signed individually, ensuring its integrity and authenticity are maintained from the sender to the final recipient, regardless of how many intermediaries handle it.
    • Non-repudiation: The signature provides proof of the sender’s identity, and the sender cannot deny having sent the message, ensuring accountability.
  2. Protection Against Intermediaries

    • Intermediate Trust: HTTP Message Signatures ensure that even if data passes through untrusted intermediaries, the integrity and authenticity of the message remain intact. Intermediaries cannot alter the data without invalidating the signature.
    • Secure Delegation: In scenarios where requests are forwarded or proxied, each entity can verify the original signature, ensuring that the message has not been tampered with.
  3. Granular Security Controls

    • Request-Level Granularity: By signing individual requests, different parts of a system can enforce security policies at a more granular level. This is particularly useful in microservices architectures and APIs where different endpoints might require different security measures.
    • Selective Verification: Only specific parts of the message (such as headers or body content) can be signed and verified, providing flexibility in what needs to be protected.
  4. Compatibility with Existing Infrastructure: HTTP Message Signatures can be used in conjunction with existing infrastructure, such as load balancers or reverse proxies, without the need for TLS termination at each component. The signatures are validated at the application level, providing end-to-end security.

Example Walkthrough

Configuration

  1. Configure Signing and Verification Options: Contrary to other Gate plugins, the HTTP Message Signature plugin has a top-level configuration, as shown below:

    request_signing:
    sign_requests: true
    verify_requests: true
    block_unverified: true
    verification_keys:
    key1: |
    -----BEGIN PUBLIC KEY-----
    UFkwEwYHKoyIzj0CAQYIKoZIzj0DAQcDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPp
    Y2MAogStF33OiQj30+d/mAWM9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
    -----END PUBLIC KEY-----
    key2: |
    -----BEGIN PUBLIC KEY-----
    AFkyEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPp
    Y2MAogStF33OiQj30+d/mAWM9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
    -----END PUBLIC KEY-----
    signing_key:
    key_id: "my_key_id"
    key_value: |
    -----BEGIN EC PRIVATE KEY-----
    MHcCYTUDMIA34DuzRBiZttW9R524G2VPqt1GDTgyXE5SSFF+3NOPboAoGCCqGSM49
    AwEHoUQDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPpY2MAogStF33OiQj30+d/mAWM
    9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
    -----END EC PRIVATE KEY-----

    • sign_requests: Set to true if you want to sign all outgoing requests.
    • verify_requests: Set to true if you want to verify all incoming requests.
    • block_unverified: Set to true if you want to block requests that fail signature verification.
    • verification_keys: Provide a map of key IDs and their corresponding public keys for verification.
    • key_id: Specify the ID of the signing key.
    • signing_key: Provide the private key used for signing requests.
danger

In production the private key should be retrieved from the secret manger using the secret_engine configuration.

  1. (Optionally) Apply the Request Signature Plugin: To enable HTTP Message Signatures for your API endpoints, you can apply the plugin to the desired URL pattern:

    urls:
    - pattern: "/api/*"
    sign_req: true
    verify_req: true

    This configuration verifies all the incoming signatures to /api/* and signs all outgoing requests.

Testing

Let's run Gate to forward requests to to /api/* to localhost:8090 and enable HTTP Message Signatures:

curl --trace - -v http://gate/api
nc -l 8090
GET /api HTTP/1.1
Host: localhost:8090
User-Agent: curl/8.4.0
Accept: */*
Signature: sig=:+3s/8dSuE1arX/6QiGkafpE7eQOXO3xYfzLyPqTHakMw6dl/fiAWoQJ5zz5ysknQ9e8gzoNqj0eSq761/w4c+Q==:
Signature-Input: sig=();created=1716310006;keyid="my_key_id";alg="ecdsa-p256-sha256"
X-B3-Sampled: 1
X-B3-Spanid: 5c53064c9b5c8442
X-B3-Traceid: 564b117b5a50960efb0d655d8d2d49dc
Accept-Encoding: gzip

We can see that Gate added the Signature and Signature-Input to the request to the upstream server using the private key my_key_id associated with the Gate instance.

Conclusion

The HTTP Message Signatures plugin for Gate provides a powerful solution for securing API requests and ensuring their integrity and authenticity. By signing and verifying requests using digital signatures, you can protect your APIs from unauthorized access and tampering. The plugin offers flexibility in configuration options and seamlessly integrates with your existing URL patterns. By leveraging HTTP Message Signatures, you can enhance the security of your API ecosystem and build trust with your API consumers.