Authentication: Can we get a signed public key instead of private key


#1

Hi,
When we hit this link
https://github.com/organizations/{org}/settings/apps/{app_name}#regenerate-key
To generate a key, we are given a full private key pair with no signing authority. This is not quite right for a couple or reasons:

  1. We really don’t need a key pair. We just need 1 key to encrypt our Bearer token with.
  2. The PEM file is unsigned. This makes it vulnerable to man in the middle attack every time we request for a new key.

Both problems can be solved if we receive a properly signed public key. I realize this will be a giant change but this is the only appropriate thing to do.


#2

You’re fetching it from github.com over TLS.


#3

Sure, TLS provides a layer of security. However, wouldn’t a public key PEM be a more suitable format for us to get? We do not need a key pair because we are only encrypting the information using the private key part of the PEM.

The current implementation seems a little backward. In a asymmetric key encryption, wouldn’t you keep the private key and share the public key? It’s odd that we receive a private key and end up having to sign them ourselves so it can be used on some frameworks such as C# crypto and open SSL because it doesn’t trust unsigned certs.


#4

Yeah. You’re not wrong about this.


#5

It’s a little odd, but the private key is the trusted secret, so by standard terminology that is the one that should be used to sign requests (i.e. it would be fine for the world to know the corresponding public key). Of course private/public keys are symmetric, so it doesn’t matter much. The one thing that is a little odd is that github generates the keypair and sends it to you. A more traditional design would be the SSH design of allowing you to paste in a public key. Still, I don’t see what the problem with this is.


#6

Since the keypair is only ever used to authenticate with GitHub, I don’t think “GitHub misuses your private key” actually opens anything up in their threat model. If GitHub wants to pretend to be your app, they can just pretend to be your app. Having the private key gives them nothing of import.


#7

I agree with Keno that private key should be created by the owner without being transmitted over the wire. Public key should be handed to GitHub only.
It’s not about trusting GitHub, it’s about sharing as little secrets as possible as a basic security rule.
There are proxies in the wild which break SSL in the middle for filtering purposes, putting any payload into snakeoil antivirus applications. Common in enterprise networks. Your private key would leak here.


#8

I agree on that one


#9

Hi! I’m a member of the GitHub application security team and thought I might be able to address some of the above questions.

We really don’t need a key pair. We just need 1 key to encrypt our Bearer token with.

Which bearer token are you referring to? API Requests that require the public/private key pair don’t use a bearer token. These requests use the public/private key to verify the authenticity of the message from the sender (i.e. only a client with private key could sign a message for application X).

The PEM file is unsigned. This makes it vulnerable to man in the middle attack every time we request for a new key.

As noted above, we rely on HTTPS to prevent a man in the middle scenario. We further mitigate man in the middle scenarios by using the Strict-Transport-Security and Public-Key-Pins headers to ensure people are using HTTPS and prevent unauthorized certificates from being used.

The current implementation seems a little backward. In a asymmetric key encryption, wouldn’t you keep the private key and share the public key? It’s odd that we receive a private key and end up having to sign them ourselves so it can be used on some frameworks such as C# crypto and open SSL because it doesn’t trust unsigned certs.

In such a design we would be sharing the public key so that other people (anyone since it is public) could encrypt a payload that only we could decrypt. Instead, we are giving you the private key so that anyone, including us, can verify the authenticity of the message using a signature. The private key is a “secret” and verifying the signature proves that the client knows the secret, since only someone that knows the value can produce a valid signature.

A more traditional design would be the SSH design of allowing you to paste in a public key. Still, I don’t see what the problem with this is.

Yes…this could be something we support in the future, but don’t have anything to announce now. Unlike an SSH key, this key isn’t meant to be reused across various systems. The key is meant to only ever be used for communicating with our API for your application. As such, to ease setup, we decided to generate the key for you.

Since the keypair is only ever used to authenticate with GitHub, I don’t think “GitHub misuses your private key” actually opens anything up in their threat model.

Correct