0

Could it be practical to authenticate API request through digital signature (based on headers and message body)? This would be asymmetric instead of something like HMAC which is not a signature. Are there performance or other constraints that make this impractical?

I know JWTs can be signed with asymmetric but signing the whole message would provide the best level of non-repudiation and prevent token reuse.

1
  • The concept of signing the whole request was popular before the web moved on to HTTPS (e.g. oAuth v1). Since all services use HTTPS this is no longer necessary.
    – Robert
    Mar 11 at 22:08

2 Answers 2

1

It is possible, yes! Inherently, there's nothing preventing this from happening. You can even do it with browser clients, as JS has built in asymmetric key handling and message signing functions these days.

However, it may noticeably impact performance, especially if you use very large keys. All mainstream secure communication channels use symmetric rather than asymmetric cryptography for the bulk data (messages), because it is many times as fast (and even so, prior to AES native instructions in CPUs, it caused non-trivial CPU load on servers). Both creating and verifying asymmetric signatures is computationally expensive (how much so for each operation depends on the algorithm and the key size), and hardware acceleration for the purpose is usually unavailable. If you decide to do this, I recommend simulating the load it puts on your clients and servers (it will also slightly increase network traffic, though probably not enough to matter) before rolling it out to production. You also probably want to use ECDSA (or rather, Ed25519), rather than something like RSA or integer DSA, as secure key sizes are much smaller and faster.

Note also that you'll still have to solve the key distribution problem. Unless your clients will have their private key present in every one of their devices, they won't be able to use the service. It's important that creating and setting new public keys be a process that requires the verified proof of the client's consent, otherwise a malicious server admin (or similar) could add a new public key (one they just created) to a user's account, and then forge signatures "from that user" as non-repudiable traffic. One option here is Public Key Infrastructure (certificate authorities verifying identity in response to certificate signing requests, and issuing signed certificates containing the public keys) but there are options besides PKI as well (web of trust, external authenticated key server that has the role of a CA but doesn't issue certs per se, probably others).

You should send your traffic over TLS anyhow (you mention headers, so presumably HTTPS), with optional client certificates, for the sake of the server authentication, encryption, built-in replay protection, etc. You'll also need to think carefully about your signing scheme, especially if you have browser clients, as web content isn't allowed to even see, much less set, all headers (e.g. scripts can't see any cookie that is marked HttpOnly). Headers (most notably Content-Length) also change depending on the message; if you're not careful, adding the signature to the message could itself invalidate the signature as some of the signed data changes. You should also consider whether you want this to be bi-directional, or only require request (not response) signing.

Think carefully whether this is worth gaining non-repudiation.

1
  • I was just considering this optionally for server to server where the consumer would configure their public keys themselves through admin screens and those actions would be recorded in audit logs. And also configure keys on their servers. It seems like it might not be worth the performance overhead.
    – jhurtas
    Mar 12 at 17:47
0

Yes, you can use PKI client certificates to authenticate an API client. It's just another authentication method really.

You have to work out the PKI infrastructure like CSR for each client, managing the CA, revocation, expiration, and the rest. More overhead than passwords or tokens, but certainly provides for non-repudiation. You would have to work out if all that's feasible for your use case.

Azure implements one here for it's API Management https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-mutual-certificates-for-clients

Here's some good analysis of using X.509 certs for asymmetrical encryption on an API https://nevatech.com/blog/post/What-you-need-to-know-about-securing-APIs-with-mutual-certificates

3
  • Note that TLS client certificates do NOT provide the non-repudiation property that the question asks for. They only provide authentication of the client end of the connection, not of each message. Once the TLS session is established, message authenticity uses a symmetric key that both sides know, so either side could forge messages after the fact and there'd be no way to prove either way.
    – CBHacking
    Mar 12 at 9:36
  • Yes understood. This would be on top of standard TLS, with a private PKI. A client based X.509 certificate identity would add an additional level of asymmetrical cryptography to the standard SSL/TLS channel. Mar 12 at 15:27
  • Correct the question is about signing the request content, not client authentication e.g. mTLS
    – jhurtas
    Mar 12 at 17:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.