0

I have a webapp that sends payloads to clients. I want to sign these payloads so the clients can verify they are from my application. I created a public/private key pair and now need to somehow distribute the public key in a way that the clients are sure it's mine.

From what I read there are two main ways to guarantee the authencity of the the public key - use a public certificate signed by CA or implement web of trust.

I am wondering if there is a problem with the following approach. The webapp has a domain name and website served under SSL/TLS with a certificate issued by a CA. Does it provide the same/similar level of authenicty guarantee as the PKI/WOT approaches if I publish the public key under a well-known url on this website?

I've seen something similar in the context of jwt/oauth used by the cloud providers (for example https://www.googleapis.com/oauth2/v1/certs) but not sure if it's a viable approach for public keys used for digital signatures.

3
  • WRT: "there are two main ways to guarantee the authencity of the the public key - use a public certificate signed by CA or implement web of trust" - a third way to authenticate a public key is to use to Trust On First Use (TOFU) model, where the public key is pinned after the first connection. This model is often used with SSH. | WRT your approach, instead of publishing the public key under a well-known url on your website which is secured using an SSL certificate, why not just use the public key in the SSL certificate?
    – mti2935
    Commented May 14, 2021 at 17:51
  • "why not just use the public key in the SSL certificate" - I want to automatically and oftenly rotate the keys
    – RandomM
    Commented May 14, 2021 at 18:34
  • You can publish the public key on your DNS records too.
    – ThoriumBR
    Commented May 14, 2021 at 20:25

2 Answers 2

1

Publishing the public key on an HTTPS website is fine, and pretty common. However, it does introduce a security dependency between the website and the payloads. If the website goes down, payloads can't be verified. If the website is compromised, then the attacker could publish their own key on the site and send spoofed payloads that successfully pass signature validation.

Other options include:

  • Publishing the public key as a DNS TXT record, with DNSSEC. Less attack surface than a website, but still creates a new security dependency. Means security of your payload signing key depends on security of your DNS registrar account. Clients must validate the DNSSEC signature or else an attacker can use a DNS spoofing attack to spoof the payload public key.
  • Using the public key in your TLS certificate (which is signed by a CA as belonging to you). Certificates are often harder for attackers to tamper with than website content, and an attacker can't replace the cert with their own unless they get a CA to issue one fraudulently. Means the cert and the payload signing key rotate together, but this shouldn't be a problem unless you either rotate the signing keys very frequently. Certs can be re-issued, potentially with new keys, on a pretty frequent basis (indeed, some CAs only issue short-lived certs).
  • Combination of the above: frequently-rotated public key on your website and/or DNS record, but itself signed by your TLS public key. This prevents an attacker from modifying the payload signing key without also compromising your TLS private key or replacing your TLS certificate, but allows you to rotate the TLS key and payload key independently (though you'll need to promptly update the payload key signature whenever you rotate the TLS key).
  • Giving each client the current and future keys through some authenticated method (such as a download from a TLS-protected website), with scheduled rotations, and periodically supplying more keys as the old ones rotate out. Requires that the client have secure and persistent data storage for the keys and potentially complicates onboarding new clients (if you can't just embed the keys in an app bundle or something) and handling unscheduled rotations. A compromise of the authenticated distribution channel may result in some clients having compromised keys with a long duration, which could complicate incident response.
  • Giving each client their own keys (typically a primary and a backup). This reduces the exposure of any individual key (if your concern is that the public key might be cracked), but is otherwise probably just a higher-cost version of the above.

You might want to examine why you expect to rotate the key pair so often. Generally, this isn't needed; even relatively weak public keys should be good enough for years. Concerns such as replay attacks or known-vulnerable versions should be handled using timestamps, monotonically-increasing nonces, monotonically increasing version numbers, or so on, all of which would be signed as part of the payload.

4
  • Thank you for the detailed answer! I have two additional questions. Regarding "Combination of the above" point - if the payload public key is signed with the TLS key this will produced a self-signed cert that can't be verified, correct? Can you elaborate if this is the case and why? My second questions is about the point "Giving each client the current and future keys through some authenticated method" - isn't this a variant of what I describe in my question, i.e. distributing the keys through the https website?
    – RandomM
    Commented May 16, 2021 at 17:36
  • To the first question: X.509 Certs are simply one way (of several) to combine a public key with information about it/its bearer. It is a good way to distribute the payload public key if you're signing it. It won't be a self-signed cert, though, because that's a cert signed with its own private key. It'll be signed with a different key, the TLS private key. This still won't produce a "trusted" cert, because your TLS cert doesn't specify that its key can be used to issue (sign) certs - that is, it's not a CA - but most libraries could still import the relevant keys and check the signature.
    – CBHacking
    Commented May 17, 2021 at 10:05
  • @RandomM To the second: normally if your website hosts the key, then the site is the source of truth, the canonical version of the key. You could instead distribute both current and future keys (in a persistent form) to each client, with the promise that there will be another update before all the distributed keys are rotated out. This is mostly useful when clients might not be able to access your website, or you worry it might get compromised. It's most practical when the client is an app or similar that already needs to be downloaded from somewhere trusted.
    – CBHacking
    Commented May 17, 2021 at 10:10
  • Great explanations, much appreciated!
    – RandomM
    Commented May 17, 2021 at 11:49
0

Let's look at how something similar is done by other orgnizations:

Tor Project

GPG Signature listed on the same HTTPS web site

how-to-verify-signature

  • Install GPG
  • Fetch Developer's key
  • Verify Signature

Kali

SHA256sum listed on the same HTTPS web site.


I think that in most cases, it's easier and sufficient to go with a cryptographic hash like SHA256.

The full GPG signature is likely too high a bar for most users to deal with, but either is probably fine.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .