- How to use AWS Key Management Service (KMS) to generate and manage a secure private key that acts as the signer for your treasury wallet.
- Creating, signing and submitting transactions for your wallet, using the KMS.
Required AWS IAM Permissions
Required AWS IAM Permissions
| Permission | Purpose |
|---|---|
kms:CreateKey | Create the KMS asymmetric key for signing |
iam:CreateRole | Create the IAM role for Lambda execution |
iam:PutRolePolicy | Attach inline policies to the IAM role |
iam:PutGroupPolicy | Configure group-level policies if needed |
ec2:DescribeVpcEndpoints | Configure VPC endpoints for private API access |
apigateway:UpdateRestApiPolicy | Update API Gateway resource policies |
Why Use AWS KMS as Signer for a Treasury Wallet?
Crossmint Treasury Wallets support a myriad of different signers. From email/phone number backed up keys, to passkeys, to bringing your own signer. AWS KMS is a fully managed service for creating, controlling, and managing cryptographic keys. Crossmint recommends using it as an external signer for treasury wallets, for bank grade security with high performance. It has the following properties:- Confidential Key Generation and Custody: generate private keys within hardware security modules (HSMs). No one —including your own team— ever sees or has access to the raw key material.
- Granular Access Control: define explicit permissions on who can perform signing operations using AWS IAM roles and policies. Integrate seamlessly with your organization’s existing authentication and authorization infrastructure.
- Advanced Observability: enable Cloud Trail to log every operation, and use Cloud Watch for anomaly detection and alerting.
- High Performance: operate over 1000 TPS with tens of milliseconds of latency.
Integration Steps
0. Pre-requisites
Before you begin, ensure you have:- An AWS account with appropriate permissions to create KMS keys, IAM roles, Lambda functions, and API Gateway resources
- AWS CLI installed on your machine (for testing)
1. Create a key in AWS KMS
Create an asymmetric key in AWS KMS that will be used as your wallet signerAccess AWS KMS
Create a Customer Managed Key
Configure Key Settings
| Setting | Value |
|---|---|
| Key type | Asymmetric |
| Key usage | Sign and verify |
| Key spec | ECC_SECG_P256K1 |
ECC_SECG_P256K1 specification is the secp256k1 elliptic curve, which is the same curve used by Ethereum and other EVM-compatible blockchains for cryptographic operations.Name Your Key
treasuryABC-admin-signer.Set Permissions
Copy the Public Key
2. Set up KMS Signing Policy
Next, create an IAM role that allows to call KMS for signing operations.Create a New Role
Configure Role Type
Skip Permission Policies
Name the Role
adminSignerInvoker.Add Inline Policy
Configure the Policy
| Placeholder | Where to Find It |
|---|---|
REGION | Your AWS region (e.g., us-east-1, eu-north-1) |
ACCOUNT_ID | Click your profile icon in the top-right corner of AWS Console |
KEY_ID | Found on your KMS key’s dashboard page |
Save the Policy
kms.policy) and click “Create policy”.3. Create a Crossmint Treasury Wallet with Key as a Signer
Follow the steps on the Treasury Wallets quickstart, passing the public key created earlier as the signer address. Since AWS KMS provides the public key in PEM format, you need to convert it to an Ethereum address. The code below handles this conversion by parsing the PEM-encoded public key and deriving the corresponding Ethereum address.publicKeyPem placeholder with the public key you copied from AWS KMS in the previous step.Required npm packages
Required npm packages
viem package should already be available as a peer dependency of @crossmint/wallets-sdk.4. Create a Lambda Function to Handle Signature Requests
Now create a Lambda function that will handle signing requests using your KMS key.Create the Function
adminSigner.Configure Execution Role
adminSignerInvoker).Set Environment Variables
KMS_KEY_ID and set it to your KMS key ID. You can find the key ID at the top of the KMS key’s dashboard page.
Add the Function Code
View Lambda Function Code
View Lambda Function Code
Deploy the Function
Optional: Expose Function as HTTP Endpoint
Create an API Gateway
Create an API Gateway
Create the API
Configure API Settings
KMS Sign API) and select a security policy that meets your requirements.Create a Method
| Setting | Value |
|---|---|
| Method type | POST |
| Lambda function | Select the Lambda function you created |
| Authorization (In Method Request Settings) | AWS IAM |
Create a Stage
prod).Deploy the API
Add Resource Policy
| Placeholder | Where to Find It |
|---|---|
REGION | Your AWS region (e.g., us-east-1, eu-north-1) |
ACCOUNT_ID | Click your profile icon in the top-right corner of AWS Console |
API_ID | Found in the API Gateway console URL or in the API’s ARN |
Save the Invoke URL
Grant User Group Access to API Gateway
- Search for IAM in the AWS Console and navigate to User groups in the left panel.
- Select the user group you want to grant access to (or create a new one).
- Go to the Permissions tab.
- Click Add permissions and select Create inline policy.
- Select the JSON tab in the policy editor.
- Paste the following policy:
| Placeholder | Where to Find It |
|---|---|
REGION | Your AWS region (e.g., us-east-1, eu-north-1) |
ACCOUNT_ID | Click your profile icon in the top-right corner of AWS Console |
API_ID | Found in the API Gateway console URL or in the API’s ARN |
STAGE | The stage name you created (e.g., prod) |
- Click Next, give the policy a name (e.g.,
api-gateway-invoke-policy), and click Create policy.
Test Using AWS CLI
Test Using AWS CLI
Open Security Credentials
Create Access Key
Select Use Case
Copy Access Keys
Run AWS Configure
aws configure to set up your AWS credentials:Enter Access Key ID
Enter Secret Access Key
Enter Default Region
us-east-1, eu-north-1).Set Output Format
json, yaml, text, or table.Your credentials will be stored in ~/.aws/credentials and your configuration in ~/.aws/config.Install awscurl
awscurl to make signed requests to your API:Generate Signature
| Placeholder | Description |
|---|---|
YOUR_REGION | Your AWS region (e.g., us-east-1, eu-north-1) |
YOUR_API_ID | Found in the API Gateway console URL or ARN (e.g., if ARN is arn:aws:execute-api:eu-north-1:257027486036:bho48fe8dl/*/POST/, then API_ID is bho48fe8dl) |
BASE64_ENCODED_MESSAGE_HASH | The base64-encoded message hash returned from wallet APIs |
0xYOUR_KMS_SIGNER_ADDRESS | The Ethereum address derived from your KMS public key (from step 3) |
5. Initiate Regulated Transfer
Initiate a regulated transfer from your treasury wallet to a recipient. Before calling the API, ensure the recipient wallet is properly set up with registered personal data as described in the regulated transfers guide. The API returns a transaction object containing amessage (hash) that needs to be signed by the adminSigner.
6. Sign the Message
Send the message hash returned from the previous step to your AWS API Gateway endpoint. For testing, you can use the AWS CLI to submit the signature. This would have required you to expose the lambda as an HTTP API in step 4.Install awscurl
awscurl to make signed requests to your API:Generate Signature
| Placeholder | Description |
|---|---|
YOUR_REGION | Your AWS region (e.g., us-east-1, eu-north-1) |
YOUR_API_ID | Found in the API Gateway console URL or in the API’s ARN |
BASE64_ENCODED_MESSAGE_HASH | The base64-encoded message hash returned from wallet APIs |
0xYOUR_KMS_SIGNER_ADDRESS | The Ethereum address derived from your KMS public key (from step 3) |
7. Approve the Transaction
Finally, submit the signature to the Approve Transaction API to complete the transfer. The transaction is then broadcast to the blockchain.Security Best Practices
Follow these security best practices:- Principle of Least Privilege: Only grant the minimum permissions necessary for each IAM role and user
- Audit Logging: Enable AWS CloudTrail to log all KMS and API Gateway operations
- Network Security: Consider using VPC endpoints for KMS to keep traffic within your AWS network
- Access Reviews: Regularly review who has access to your KMS keys and API Gateway endpoints

