Remote Ed25519 RPC Signer
An Ed25519 Remote RPC Signer implementation in Rust, using Zcash's ZIP215 validation rules via the ed25519-zebra >= 2
crate.
It can be used to offload Coordinator Milestone's signature generation to third-party machines, mitigating the risk of private key exposure by compromise of a single machine.
Design
The project is divided into two components: a dispatcher
and a signer
. The dispatcher
is the sole endpoint that Coordinator implementations will use, it does not hold any private key material, and it simply maps requests to the signer
services holding the corresponding private key.
The signer
service receives the message to be signed, and generates signatures according to the public keys requested, if an exact match is found.
The dispatcher
and signer
authenticate each other using TLS mutual authentication.
RPC Definition
Dispatcher
syntax = "proto3";
package dispatcher;
service SignatureDispatcher {
rpc SignMilestone (SignMilestoneRequest) returns (SignMilestoneResponse);
}
message SignMilestoneRequest {
repeated bytes pubKeys = 1;
bytes msEssence = 2;
}
message SignMilestoneResponse {
repeated bytes signatures = 1;
}
Signer
syntax = "proto3";
package signer;
service Signer {
rpc SignWithKey (SignWithKeyRequest) returns (SignWithKeyResponse);
}
message SignWithKeyRequest {
bytes pubKey = 1;
bytes msEssence = 2;
}
message SignWithKeyResponse {
bytes signature = 1;
}
Example configuration
Dispatcher
The dispatcher
simply maps public keys to the signer
endpoint holding the corresponding private key.
{
"bind_addr": "0.0.0.0:50051",
"signers": [
{
"pubkey": "268783e7277c7c9f6dc898d08f5ca458941de2eb339e7da948239cc3647dffcc",
"endpoint": "http://signer1.remote-signer:50052"
},
{
"pubkey": "d578d0a8e5392040cf5c3ba0153c28c300d8eaed3d8d7ef43729cadfe1e2467b",
"endpoint": "http://signer2.remote-signer:50053"
}
],
"tlsauth": {
"ca": "ssl/ca.crt",
"client_cert": "ssl/dispatcher.remote-signer.crt",
"client_key": "ssl/dispatcher.remote-signer_plain.key"
}
}
Signer
On the other hand the signer
holds the private key material corresponding to mapped public keys.
{
"bind_addr": "0.0.0.0:50052",
"keys": [
{
"pubkey": "268783e7277c7c9f6dc898d08f5ca458941de2eb339e7da948239cc3647dffcc",
"privkey": "[REDACTED]"
}
],
"tls": {
"ca": "ssl/ca.crt",
"cert": "ssl/signer1.remote-signer.crt",
"key": "ssl/signer1.remote-signer_plain.key"
}
}
{
"bind_addr": "0.0.0.0:50053",
"keys": [
{
"pubkey": "d578d0a8e5392040cf5c3ba0153c28c300d8eaed3d8d7ef43729cadfe1e2467b",
"privkey": "[REDACTED]"
}
],
"tls": {
"ca": "ssl/ca.crt",
"cert": "ssl/signer2.remote-signer.crt",
"key": "ssl/signer2.remote-signer_plain.key"
}
}