solana-kms-signer 0.1.0 → 1.0.2
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.
- package/README.md +82 -27
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/kms/client.d.ts.map +1 -1
- package/dist/kms/client.js +1 -1
- package/dist/kms/client.js.map +1 -1
- package/dist/kms/signer.d.ts +2 -2
- package/dist/kms/signer.d.ts.map +1 -1
- package/dist/kms/signer.js +2 -2
- package/dist/kms/signer.js.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/publicKey.js.map +1 -1
- package/package.json +17 -16
- package/src/errors/index.test.ts +185 -170
- package/src/errors/index.ts +21 -12
- package/src/index.ts +10 -14
- package/src/kms/client.test.ts +318 -255
- package/src/kms/client.ts +100 -98
- package/src/kms/signer.test.ts +415 -396
- package/src/kms/signer.ts +205 -209
- package/src/types/index.ts +27 -27
- package/src/utils/publicKey.test.ts +178 -119
- package/src/utils/publicKey.ts +34 -34
package/src/kms/client.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
GetPublicKeyCommand,
|
|
3
|
+
KMSClient,
|
|
4
|
+
SignCommand,
|
|
5
5
|
} from '@aws-sdk/client-kms';
|
|
6
|
-
import type { KmsConfig } from '../types/index.js';
|
|
7
6
|
import { KmsClientError } from '../errors/index.js';
|
|
7
|
+
import type { KmsConfig } from '../types/index.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* AWS KMS client wrapper for ED25519 key operations.
|
|
@@ -24,109 +24,111 @@ import { KmsClientError } from '../errors/index.js';
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export class KmsClient {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
private readonly kmsClient: KMSClient;
|
|
28
|
+
private readonly config: KmsConfig;
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new KmsClient instance.
|
|
32
|
+
*
|
|
33
|
+
* @param config - Configuration for AWS KMS connection
|
|
34
|
+
*/
|
|
35
|
+
constructor(config: KmsConfig) {
|
|
36
|
+
this.config = config;
|
|
37
|
+
this.kmsClient = new KMSClient({
|
|
38
|
+
region: config.region,
|
|
39
|
+
credentials: config.credentials,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Retrieves the public key from AWS KMS.
|
|
45
|
+
*
|
|
46
|
+
* Returns DER-encoded SubjectPublicKeyInfo (X.509 format).
|
|
47
|
+
* Use `extractEd25519PublicKey` to extract the raw 32-byte public key.
|
|
48
|
+
*
|
|
49
|
+
* @returns DER-encoded public key as Uint8Array (typically 42-44 bytes)
|
|
50
|
+
* @throws {KmsClientError} If KMS API call fails
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const derPublicKey = await client.getPublicKey();
|
|
55
|
+
* const rawPublicKey = extractEd25519PublicKey(derPublicKey);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
async getPublicKey(): Promise<Uint8Array> {
|
|
59
|
+
try {
|
|
60
|
+
const command = new GetPublicKeyCommand({
|
|
61
|
+
KeyId: this.config.keyId,
|
|
62
|
+
});
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
const response = await this.kmsClient.send(command);
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
if (!response.PublicKey) {
|
|
67
|
+
throw new KmsClientError(
|
|
68
|
+
'GetPublicKey response missing PublicKey field',
|
|
69
|
+
);
|
|
70
|
+
}
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
// Convert Buffer/Uint8Array to Uint8Array
|
|
73
|
+
return new Uint8Array(response.PublicKey);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof KmsClientError) {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
throw new KmsClientError(
|
|
79
|
+
`Failed to get public key from KMS: ${error instanceof Error ? error.message : String(error)}`,
|
|
80
|
+
error,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Signs a message using the ED25519 key in AWS KMS.
|
|
87
|
+
*
|
|
88
|
+
* @param message - Message to sign as Uint8Array
|
|
89
|
+
* @returns ED25519 signature (64 bytes)
|
|
90
|
+
* @throws {KmsClientError} If KMS API call fails or signature is invalid
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const message = new TextEncoder().encode('Hello, Solana!');
|
|
95
|
+
* const signature = await client.sign(message);
|
|
96
|
+
* console.log('Signature length:', signature.length); // 64
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
async sign(message: Uint8Array): Promise<Uint8Array> {
|
|
100
|
+
try {
|
|
101
|
+
const command = new SignCommand({
|
|
102
|
+
KeyId: this.config.keyId,
|
|
103
|
+
Message: message,
|
|
104
|
+
MessageType: 'RAW',
|
|
105
|
+
SigningAlgorithm: 'ED25519_SHA_512',
|
|
106
|
+
});
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
const response = await this.kmsClient.send(command);
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
if (!response.Signature) {
|
|
111
|
+
throw new KmsClientError('Sign response missing Signature field');
|
|
112
|
+
}
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
const signature = new Uint8Array(response.Signature);
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
// Validate signature length (ED25519 signatures are always 64 bytes)
|
|
117
|
+
if (signature.length !== 64) {
|
|
118
|
+
throw new KmsClientError(
|
|
119
|
+
`Invalid signature length: expected 64 bytes, got ${signature.length} bytes`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
return signature;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error instanceof KmsClientError) {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
throw new KmsClientError(
|
|
129
|
+
`Failed to sign message with KMS: ${error instanceof Error ? error.message : String(error)}`,
|
|
130
|
+
error,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
132
134
|
}
|