The Oracle service now supports Hardware Security Module (HSM) backed key management through AWS KMS and Google Cloud KMS. This eliminates the security risk of exposing private keys in environment variables.
All key providers implement the KeyProvider interface:
interface KeyProvider {
getPublicKey(): Promise<string>;
getPublicKeyBuffer(): Promise<Buffer>;
sign(data: Buffer): Promise<Buffer>;
getProviderType(): string;
}-
EnvKeyProvider (Development/Testing)
- Loads private key from
ORACLE_PRIVATE_KEYenvironment variable ⚠️ Private key is stored in memory- Use only for development and testing
- Loads private key from
-
AwsKmsKeyProvider (Production)
- Uses AWS Key Management Service
- Private key never leaves the HSM
- Signing operations performed in AWS infrastructure
-
GcpKmsKeyProvider (Production)
- Uses Google Cloud Key Management Service
- Private key never leaves the HSM
- Signing operations performed in Google Cloud infrastructure
# .env
KEY_PROVIDER=env
ORACLE_PRIVATE_KEY=S... # Stellar secret key# .env
KEY_PROVIDER=aws-kms
AWS_REGION=us-east-1
AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012
# AWS credentials (via environment or IAM role)
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...# .env
KEY_PROVIDER=gcp-kms
GCP_PROJECT_ID=my-project
GCP_LOCATION_ID=global
GCP_KEY_RING_ID=oracle-keys
GCP_KEY_ID=oracle-signing-key
GCP_KEY_VERSION=1
# GCP credentials (via GOOGLE_APPLICATION_CREDENTIALS or default credentials)
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.jsoncd oracle
npm install @aws-sdk/client-kms# Create a KMS key for signing
aws kms create-key \
--description "Oracle signing key" \
--key-usage SIGN_VERIFY \
--key-spec ECC_SECG_P256K1
# Note: AWS KMS doesn't natively support Ed25519
# For Ed25519, consider AWS CloudHSM or store public key separatelyCreate an IAM policy with the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Sign",
"kms:GetPublicKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:REGION:ACCOUNT:key/KEY_ID"
}
]
}Attach this policy to:
- The IAM user (if using access keys)
- The IAM role (if using EC2/ECS/EKS)
# Set environment variables
export KEY_PROVIDER=aws-kms
export AWS_REGION=us-east-1
export AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/...cd oracle
npm install @google-cloud/kms# Set variables
PROJECT_ID=my-project
LOCATION=global
KEY_RING=oracle-keys
KEY_NAME=oracle-signing-key
# Create key ring
gcloud kms keyrings create $KEY_RING \
--location $LOCATION \
--project $PROJECT_ID
# Create signing key with Ed25519
gcloud kms keys create $KEY_NAME \
--keyring $KEY_RING \
--location $LOCATION \
--purpose asymmetric-signing \
--default-algorithm ec-sign-ed25519 \
--project $PROJECT_ID# Create service account
gcloud iam service-accounts create oracle-signer \
--display-name "Oracle Signing Service" \
--project $PROJECT_ID
# Grant permissions
gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring $KEY_RING \
--location $LOCATION \
--member "serviceAccount:oracle-signer@${PROJECT_ID}.iam.gserviceaccount.com" \
--role roles/cloudkms.signerVerifier \
--project $PROJECT_ID
# Create and download key
gcloud iam service-accounts keys create oracle-key.json \
--iam-account oracle-signer@${PROJECT_ID}.iam.gserviceaccount.com \
--project $PROJECT_ID# Set environment variables
export KEY_PROVIDER=gcp-kms
export GCP_PROJECT_ID=my-project
export GCP_LOCATION_ID=global
export GCP_KEY_RING_ID=oracle-keys
export GCP_KEY_ID=oracle-signing-key
export GCP_KEY_VERSION=1
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/oracle-key.json# k8s/deployment.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: oracle-service
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/oracle-kms-role
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oracle
spec:
template:
spec:
serviceAccountName: oracle-service
containers:
- name: oracle
env:
- name: KEY_PROVIDER
value: "aws-kms"
- name: AWS_REGION
value: "us-east-1"
- name: AWS_KMS_KEY_ID
valueFrom:
secretKeyRef:
name: oracle-secrets
key: kms-key-id# k8s/deployment.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: oracle-service
annotations:
iam.gke.io/gcp-service-account: oracle-signer@PROJECT.iam.gserviceaccount.com
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oracle
spec:
template:
spec:
serviceAccountName: oracle-service
containers:
- name: oracle
env:
- name: KEY_PROVIDER
value: "gcp-kms"
- name: GCP_PROJECT_ID
value: "my-project"
- name: GCP_LOCATION_ID
value: "global"
- name: GCP_KEY_RING_ID
value: "oracle-keys"
- name: GCP_KEY_ID
value: "oracle-signing-key"-
Backup Current Setup
# Save current private key securely echo $ORACLE_PRIVATE_KEY > backup-key.txt chmod 600 backup-key.txt
-
Set Up HSM Provider
- Follow AWS KMS or GCP KMS setup instructions above
- Test in a staging environment first
-
Update Configuration
# Update environment variables export KEY_PROVIDER=aws-kms # or gcp-kms # Add provider-specific variables
-
Deploy and Verify
# Deploy updated configuration kubectl apply -f k8s/ # Check logs kubectl logs -f deployment/oracle # Look for: "KeyService initialized with aws-kms provider"
-
Remove Old Private Key
# After successful verification unset ORACLE_PRIVATE_KEY # Remove from secrets/config
- Use HSM providers (AWS KMS, GCP KMS) in production
- Rotate KMS keys regularly
- Use IAM roles/Workload Identity instead of static credentials
- Monitor KMS API usage for anomalies
- Enable CloudTrail/Cloud Audit Logs for KMS operations
- Use separate KMS keys for different environments
- Use
EnvKeyProviderin production - Store private keys in version control
- Share KMS keys across multiple services
- Grant overly broad KMS permissions
- Disable audit logging
cd oracle
npm install @aws-sdk/client-kmsCheck IAM permissions:
aws kms get-public-key --key-id $AWS_KMS_KEY_IDcd oracle
npm install @google-cloud/kmsCheck service account permissions:
gcloud kms keys get-iam-policy $KEY_NAME \
--keyring $KEY_RING \
--location $LOCATIONCheck application logs:
# Should see one of:
# "KeyService initialized with env provider"
# "KeyService initialized with aws-kms provider"
# "KeyService initialized with gcp-kms provider"- EnvKeyProvider: <1ms (in-memory)
- AwsKmsKeyProvider: 10-50ms (network call to AWS)
- GcpKmsKeyProvider: 10-50ms (network call to GCP)
Public keys are cached after first retrieval to minimize HSM calls.
- AWS KMS: 1,200 requests/second (shared across operations)
- GCP KMS: 60,000 requests/minute
For high-throughput scenarios, consider request batching or caching strategies.
- Key storage: $1/month per key
- Signing operations: $0.03 per 10,000 requests
- Key storage: $0.06/month per key version
- Signing operations: $0.03 per 10,000 requests
Example: 1M signatures/month = ~$3 in signing costs