I'm currently building an application whose only real complexity lies in private key security. I don't feel comfortable keeping the private key in the disk image, from which the server would read it, so I've thought about building a dedicated "signing service" which listens for an incoming connection on boot up, from which it will receive the private key over HTTPS from an offline server, that will be connected to the internet briefly, in order to send the private key to the web service. This service would, effectively, mimic a Hardware Security Module (HSM), but at the cost of a cloud VM, which is a fraction of that of a HSM.
In addition to this, the signing service, which receives the private key in this manner, will expose a safe interface, rather than an interface which allows signing arbitrary messages. So, for example, the service could be set up to expose an interface that accepts a list of transactions that pay to a pre-defined set of "receive addresses", and then the service would return a signed transaction that moves the value from all these receive addresses to the private key it controls.
In other words, the private key would reside in the memory space of the application which only exposes a safe interface, thereby requiring that an attacker compromise the VM on which this application is running, and read the private key from the memory space of the application process. Penetrating the cloud environment, thus, would not cause either private key loss or enable the attacker to sign arbitrary messages.
- Does this approach make sense? Does it offer a gain in security?
- Which security-related issues should I be aware of in sending the private key to the web service?
- IP-related: The program that sends the private key to the web service would send based on the IP address of the web service. How difficult would it be for an attacker to receive this data, destined for the service? Should I set up a VPN between the network from which the key will be sent and the cloud environment?
- Google Cloud has an HTTPS load balancer, which you can give your HTTPS private key, and it will sit in front of your app and shuffle requests to it, thus putting Google in charge of authenticating the VMs running in the cloud environment (from which our signing service will be receiving the private key). Thus, if we 1) connect to the signing service's IP (in order to arm it with the private key) and 2) verify the certificate is authentic, it would mean an attacker would need to compromise Google Cloud's HTTPS proxy service in order to receive the private key, by 1) man-in-the-middling the connection destined for the VM and 2) using the private key held by Google Cloud to sign the HTTPS request as authentic. Would this make sense as a way of outsourcing private key security? (Private key theft could also occur by the attacker running his own disk image in our cloud environment, which just sends the received private key to himself, but this could be avoided by requiring disk images running in our cloud environment to be signed with a key that is also kept offline (eg. in the same place as the signing service private key))
So, the HSM (the VM running the signing service) 1) exposes a safe interface for message signing and 2) keeps the private key in the same memory space as the logic that restricts its use. An Amazon AWS HSM costs around $10,000/year, so this would, in effect, mimic such a device at a fraction of the cost (provided it's safe).