hyperledger-firefly / hyperledger-firefly/signer

Add AWS KMS signing backend

Open
#117 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
14
Forks
19
Avg merge
17h 12m
Merged PRs (30d)
3

Description

## Feature Request: Add AWS KMS signing backend

### Summary

Add an AWS KMS signing backend so the FireFly Signer can sign Ethereum transactions using keys stored in AWS KMS, without the key material ever leaving the KMS hardware.

### Motivation

Currently, FireFly Signer only supports a file-based wallet (`fileWallet`) where signing keys live on disk. For enterprise and regulated deployments (financial services, tokenised assets, etc.), there is a strong requirement to use hardware-backed key management:

- **Key isolation:** the private key never exists in process memory or on disk — signing happens inside KMS.
- **FIPS 140-2 Level 3 compliance:** KMS is FIPS-validated, which institutional auditors require.
- **Key rotation without restart:** KMS keys can be rotated at the AWS level without touching the signer.
- **Audit trail:** every signing operation is logged in CloudTrail with the KMS key ID.
- **IRSA integration:** on EKS, the signer pod can use IAM Roles for Service Accounts to authenticate to KMS — no long-lived credentials.

AWS KMS supports asymmetric keys on the `ECC_SECGP256K1` curve (the secp256k1 curve used by Ethereum), so KMS can produce valid Ethereum signatures.

### Proposed Implementation

I have a working implementation ready as a PR. It adds:

1. **`pkg/kmswallet/`** — a new `KMSWallet` type that implements the existing `ethsigner.Wallet` interface. Internally it:
- Calls `kms:GetPublicKey` at startup to derive the Ethereum address from the KMS public key.
- Calls `kms:Sign` with `MessageType: Digest` and `SigningAlgorithm: ECDSA_SHA_256` for each signing request.
- Parses the DER-encoded ECDSA signature to extract R and S.
- Recovers the Y-parity (V) by trying both 27 and 28 and checking which recovers to the known public key (KMS does not return a recovery ID).

2. **`pkg/kmswallet/kmssigner.go`** — a `kmsSigner` that implements the `secp256k1.Signer` and `secp256k1.SignerDirect` interfaces, so it slots into the existing transaction signing path without changes.

3. **Config section `kmsWallet`** alongside `fileWallet`:
```yaml
kmsWallet:
enabled: true
keyId:
region:
endpoint:
```
When `kmsWallet.enabled` is true, it takes precedence over `fileWallet`. Defaults to false (backwards-compatible).

### Design Decisions

- **V recovery by trial:** KMS returns a DER ECDSA signature without a recovery ID. The implementation tries both parities (V=27, V=28) and checks which one recovers to the KMS public key's address. This is the same approach used by other KMS-backed Ethereum signers.
- **Pre-hashed messages:** the signer receives the already-hashed (Keccak-256) transaction payload and passes it to KMS as a `Digest`. KMS does not re-hash it.
- **Backwards-compatible:** `fileWallet` remains the default. `kmsWallet` is opt-in.
- **No multi-key support (yet):** the initial implementation supports one KMS key per signer instance (one address in `eth_accounts`). Multi-key support can be added later by mapping addresses to KMS key IDs.

### Testing

The PR includes the implementation and passes all existing tests. I plan to add integration tests with LocalStack (via the `endpoint` config) in a follow-up if there's interest from maintainers.

### Open Questions for Maintainers

1. Is there appetite for this feature in the project? I'm happy to maintain it long-term.
2. Would you prefer the V-recovery approach, or should we explore whether KMS can return the recovery ID via a different API?
3. Any preference on the config structure — should `kmsWallet` be under a broader `wallets` section, or is a top-level section fine?

Contributor guide

Open the contributing guide

Research direction

Start by reading the existing fileWallet path and the ethsigner.Wallet and secp256k1 signer interfaces, then review the proposed pkg/kmswallet/ and pkg/kmswallet/kmssigner.go entry points. Verify the kmsWallet configuration, KMS public-key and signing flow, V recovery, and compatibility with existing tests; done means the feature is tested without changing the fileWallet default.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, go
Domain
backend, cloud, cryptography, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.