@solana/keychain-aws-kms 0.0.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,174 @@
1
+ import { DescribeKeyCommand, KMSClient, MessageType, SignCommand, SigningAlgorithmSpec } from '@aws-sdk/client-kms';
2
+ import { assertIsAddress } from '@solana/addresses';
3
+ import { createSignatureDictionary, SignerErrorCode, throwSignerError } from '@solana/keychain-core';
4
+ /**
5
+ * AWS KMS-based signer using EdDSA (Ed25519) signing
6
+ *
7
+ * The AWS KMS key must be created with:
8
+ * - Key spec: ECC_NIST_EDWARDS25519
9
+ * - Key usage: SIGN_VERIFY
10
+ *
11
+ * Example AWS CLI command to create a key:
12
+ * ```bash
13
+ * aws kms create-key \
14
+ * --key-spec ECC_NIST_EDWARDS25519 \
15
+ * --key-usage SIGN_VERIFY \
16
+ * --description "Solana signing key"
17
+ * ```
18
+ */
19
+ export class AwsKmsSigner {
20
+ constructor(config) {
21
+ if (!config.keyId) {
22
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
23
+ message: 'Missing required keyId field',
24
+ });
25
+ }
26
+ if (!config.publicKey) {
27
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
28
+ message: 'Missing required publicKey field',
29
+ });
30
+ }
31
+ try {
32
+ assertIsAddress(config.publicKey);
33
+ this.address = config.publicKey;
34
+ }
35
+ catch (error) {
36
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
37
+ cause: error,
38
+ message: 'Invalid Solana public key format',
39
+ });
40
+ }
41
+ this.keyId = config.keyId;
42
+ this.requestDelayMs = config.requestDelayMs || 0;
43
+ this.validateRequestDelayMs(this.requestDelayMs);
44
+ // Create AWS KMS client
45
+ const clientConfig = {};
46
+ if (config.region) {
47
+ clientConfig.region = config.region;
48
+ }
49
+ if (config.credentials) {
50
+ clientConfig.credentials = config.credentials;
51
+ }
52
+ this.client = new KMSClient(clientConfig);
53
+ }
54
+ /**
55
+ * Validate request delay ms
56
+ */
57
+ validateRequestDelayMs(requestDelayMs) {
58
+ if (requestDelayMs < 0) {
59
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
60
+ message: 'requestDelayMs must not be negative',
61
+ });
62
+ }
63
+ if (requestDelayMs > 3000) {
64
+ console.warn('requestDelayMs is greater than 3000ms, this may result in blockhash expiration errors for signing messages/transactions');
65
+ }
66
+ }
67
+ /**
68
+ * Add delay between concurrent requests
69
+ */
70
+ async delay(index) {
71
+ if (this.requestDelayMs > 0 && index > 0) {
72
+ await new Promise(resolve => setTimeout(resolve, index * this.requestDelayMs));
73
+ }
74
+ }
75
+ /**
76
+ * Sign message bytes using AWS KMS EdDSA signing
77
+ */
78
+ async signBytes(messageBytes) {
79
+ try {
80
+ const command = new SignCommand({
81
+ KeyId: this.keyId,
82
+ Message: messageBytes,
83
+ MessageType: MessageType.RAW,
84
+ SigningAlgorithm: SigningAlgorithmSpec.ED25519_SHA_512,
85
+ });
86
+ const response = await this.client.send(command);
87
+ if (!response.Signature) {
88
+ throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
89
+ message: 'No signature in AWS KMS response',
90
+ });
91
+ }
92
+ // Ed25519 signatures are 64 bytes
93
+ const signature = new Uint8Array(response.Signature);
94
+ if (signature.length !== 64) {
95
+ throwSignerError(SignerErrorCode.SIGNING_FAILED, {
96
+ message: `Invalid signature length: expected 64 bytes, got ${signature.length}`,
97
+ });
98
+ }
99
+ return signature;
100
+ }
101
+ catch (error) {
102
+ // Re-throw SignerError as-is
103
+ if (error instanceof Error && error.name === 'SignerError') {
104
+ throw error;
105
+ }
106
+ if (error instanceof Error) {
107
+ // AWS SDK errors
108
+ const awsError = error;
109
+ throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
110
+ cause: error,
111
+ message: `AWS KMS Sign operation failed: ${awsError.message || error.message}`,
112
+ status: awsError.$metadata?.httpStatusCode,
113
+ });
114
+ }
115
+ throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
116
+ cause: error,
117
+ message: 'AWS KMS Sign operation failed',
118
+ });
119
+ }
120
+ }
121
+ /**
122
+ * Sign multiple messages using AWS KMS
123
+ */
124
+ async signMessages(messages) {
125
+ return await Promise.all(messages.map(async (message, index) => {
126
+ await this.delay(index);
127
+ const messageBytes = message.content instanceof Uint8Array
128
+ ? message.content
129
+ : new Uint8Array(Array.from(message.content));
130
+ const signatureBytes = await this.signBytes(messageBytes);
131
+ return createSignatureDictionary({
132
+ signature: signatureBytes,
133
+ signerAddress: this.address,
134
+ });
135
+ }));
136
+ }
137
+ /**
138
+ * Sign multiple transactions using AWS KMS
139
+ */
140
+ async signTransactions(transactions) {
141
+ return await Promise.all(transactions.map(async (transaction, index) => {
142
+ await this.delay(index);
143
+ // Sign the transaction message bytes
144
+ const signatureBytes = await this.signBytes(new Uint8Array(transaction.messageBytes));
145
+ return createSignatureDictionary({
146
+ signature: signatureBytes,
147
+ signerAddress: this.address,
148
+ });
149
+ }));
150
+ }
151
+ /**
152
+ * Check if AWS KMS is available and the key is accessible
153
+ */
154
+ async isAvailable() {
155
+ try {
156
+ const command = new DescribeKeyCommand({
157
+ KeyId: this.keyId,
158
+ });
159
+ const response = await this.client.send(command);
160
+ if (!response.KeyMetadata) {
161
+ return false;
162
+ }
163
+ // Verify the key spec is ECC_NIST_EDWARDS25519
164
+ const keySpec = response.KeyMetadata.KeySpec;
165
+ const keyUsage = response.KeyMetadata.KeyUsage;
166
+ const keyState = response.KeyMetadata.KeyState;
167
+ return keySpec === 'ECC_NIST_EDWARDS25519' && keyUsage === 'SIGN_VERIFY' && keyState === 'Enabled';
168
+ }
169
+ catch {
170
+ return false;
171
+ }
172
+ }
173
+ }
174
+ //# sourceMappingURL=aws-kms-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws-kms-signer.js","sourceRoot":"","sources":["../src/aws-kms-signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { AwsKmsSigner } from './aws-kms-signer.js';
2
+ export type { AwsKmsSignerConfig, AwsCredentials, KmsKeyMetadata } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { AwsKmsSigner } from './aws-kms-signer.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Configuration for creating an AwsKmsSigner
3
+ */
4
+ export interface AwsKmsSignerConfig {
5
+ /** Optional AWS credentials (defaults to default credential provider chain) */
6
+ credentials?: AwsCredentials;
7
+ /** AWS KMS key ID or ARN (must be an ECC_NIST_EDWARDS25519 key) */
8
+ keyId: string;
9
+ /** Solana public key (base58) corresponding to the AWS KMS key */
10
+ publicKey: string;
11
+ /** Optional AWS region (defaults to default region from AWS config) */
12
+ region?: string;
13
+ /** Optional delay in ms between concurrent signing requests to avoid rate limits (default: 0) */
14
+ requestDelayMs?: number;
15
+ }
16
+ /**
17
+ * AWS credentials configuration
18
+ */
19
+ export interface AwsCredentials {
20
+ accessKeyId: string;
21
+ secretAccessKey: string;
22
+ sessionToken?: string;
23
+ }
24
+ /**
25
+ * AWS KMS key metadata for validation
26
+ */
27
+ export interface KmsKeyMetadata {
28
+ /** The AWS account ID that owns the key */
29
+ AWSAccountId?: string;
30
+ /** The key ID */
31
+ KeyId: string;
32
+ /** The key spec (must be ECC_NIST_EDWARDS25519 for EdDSA) */
33
+ KeySpec: 'ECC_NIST_EDWARDS25519';
34
+ /** The key state */
35
+ KeyState: 'Disabled' | 'Enabled' | 'PendingDeletion' | 'PendingImport';
36
+ /** The key usage (must be SIGN_VERIFY for signing) */
37
+ KeyUsage: 'SIGN_VERIFY';
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,OAAO,EAAE,uBAAuB,CAAC;IACjC,oBAAoB;IACpB,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,iBAAiB,GAAG,eAAe,CAAC;IACvE,sDAAsD;IACtD,QAAQ,EAAE,aAAa,CAAC;CAC3B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,12 +1,58 @@
1
1
  {
2
2
  "name": "@solana/keychain-aws-kms",
3
- "version": "0.0.0",
4
- "main": "index.js",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
3
+ "author": "Solana Foundation",
4
+ "version": "0.2.1",
5
+ "description": "AWS KMS-based signer for Solana transactions using EdDSA (Ed25519)",
6
+ "license": "MIT",
7
+ "repository": "https://github.com/solana-foundation/solana-keychain",
8
+ "keywords": [
9
+ "solana",
10
+ "signing",
11
+ "wallet",
12
+ "aws",
13
+ "kms",
14
+ "ed25519",
15
+ "eddsa"
16
+ ],
17
+ "type": "module",
18
+ "sideEffects": false,
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "src"
30
+ ],
31
+ "dependencies": {
32
+ "@aws-sdk/client-kms": "^3.700.0",
33
+ "@solana/addresses": "^5.0.0",
34
+ "@solana/codecs-strings": "^5.0.0",
35
+ "@solana/keys": "^5.0.0",
36
+ "@solana/signers": "^5.0.0",
37
+ "@solana/transactions": "^5.0.0",
38
+ "@solana/keychain-core": "0.2.1"
39
+ },
40
+ "devDependencies": {
41
+ "dotenv": "^17.2.3",
42
+ "@solana/keychain-test-utils": "0.2.1"
7
43
  },
8
- "keywords": [],
9
- "author": "",
10
- "license": "ISC",
11
- "description": ""
12
- }
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc --build",
49
+ "clean": "rm -rf dist *.tsbuildinfo",
50
+ "test": "vitest run",
51
+ "test:unit": "vitest run --config ../../vitest.config.unit.ts",
52
+ "test:integration": "vitest run --config ../../vitest.config.integration.ts",
53
+ "test:watch": "vitest",
54
+ "test:watch:unit": "vitest --config ../../vitest.config.unit.ts",
55
+ "test:watch:integration": "vitest --config ../../vitest.config.integration.ts",
56
+ "typecheck": "tsc --noEmit"
57
+ }
58
+ }