@tnaka-dev/aws-kms-ethers-v6-signer 1.0.5
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/LICENSE +21 -0
- package/README.md +224 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +222 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nakagawa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# aws-kms-ethers-v6-signer
|
|
2
|
+
|
|
3
|
+
A signer implementation for ethers.js v6 that uses AWS Key Management Service (KMS) for secure cryptographic signing operations.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @tnaka-dev/aws-kms-ethers-v6-signer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Create AwsKmsSigner
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { ethers } from "ethers";
|
|
17
|
+
import { KMSClientConfig } from "@aws-sdk/client-kms";
|
|
18
|
+
import { AwsKmsSigner } from "@tnaka-dev/aws-kms-ethers-v6-signer";
|
|
19
|
+
|
|
20
|
+
const keyId = "<your AWS KMS key ID>"; // Replace with your actual AWS KMS key ID
|
|
21
|
+
const config = {
|
|
22
|
+
region: "<your AWS region>", // Replace with your actual AWS region
|
|
23
|
+
credentials: {
|
|
24
|
+
accessKeyId: "<your AWS access key ID>", // Replace with your actual AWS access key ID
|
|
25
|
+
secretAccessKey: "<your AWS secret access key>", // Replace with your actual AWS secret access key
|
|
26
|
+
},
|
|
27
|
+
} as KMSClientConfig;
|
|
28
|
+
// Create the signer
|
|
29
|
+
const signer = new AwsKmsSigner(keyId, config, provider);
|
|
30
|
+
// Connect the signer to the provider
|
|
31
|
+
const provider = new ethers.JsonRpcProvider("<your Ethereum JSON-RPC node URL>"); // Replace with your actual Ethereum JSON-RPC node URL
|
|
32
|
+
const connectedSigner = signer.connect(provider);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### getAddress
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Address
|
|
39
|
+
const address = await signer.getAddress();
|
|
40
|
+
console.log("Address:", address);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### signMessage
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Sign a message
|
|
47
|
+
const message = "Hello, AWS KMS Signer!";
|
|
48
|
+
const signature = await signer.signMessage(message);
|
|
49
|
+
console.log(
|
|
50
|
+
"signMessage verification:",
|
|
51
|
+
ethers.verifyMessage(message, signature) === address,
|
|
52
|
+
);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### sendTransaction
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Sign a transaction
|
|
59
|
+
const toAddress = "<target Ethereum address>"; // Replace with the actual target Ethereum address
|
|
60
|
+
const tx = await connectedSigner.sendTransaction({
|
|
61
|
+
to: toAddress,
|
|
62
|
+
value: ethers.parseEther("0.01"),
|
|
63
|
+
});
|
|
64
|
+
const receipt = await tx.wait();
|
|
65
|
+
console.log("Transaction:", receipt?.status === 1 ? "Success" : "Failure");
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Contract call
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const toAddress = "<target Ethereum address>"; // Replace with the actual target Ethereum address
|
|
72
|
+
const contract = new ethers.Contract(
|
|
73
|
+
"<target ERC20 contract address>", // Replace with the actual target ERC20 contract address
|
|
74
|
+
[
|
|
75
|
+
"function decimals() public view returns (uint8)",
|
|
76
|
+
"function transfer(address to, uint256 value) external returns (bool)",
|
|
77
|
+
"function balanceOf(address account) external view returns (uint256)",
|
|
78
|
+
],
|
|
79
|
+
connectedSigner,
|
|
80
|
+
);
|
|
81
|
+
const decimals = await contract.decimals();
|
|
82
|
+
const tx = await contract.transfer(
|
|
83
|
+
toAddress,
|
|
84
|
+
ethers.parseUnits("100", decimals),
|
|
85
|
+
);
|
|
86
|
+
const receipt = await tx.wait();
|
|
87
|
+
console.log("ERC20 Transfer:", receipt?.status === 1 ? "Success" : "Failure");
|
|
88
|
+
console.log(
|
|
89
|
+
"toAddress amount:",
|
|
90
|
+
ethers.formatUnits(await contract.balanceOf(toAddress), decimals),
|
|
91
|
+
);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### signTypedData
|
|
95
|
+
|
|
96
|
+
Example: Signing typed data for ERC20Permit (ERC-2612) using @openzeppelin/contracts
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const contractAddress = "<target ERC20Permit(ERC-2612) contract address>"; // Replace with the actual target ERC20Permit(ERC-2612) contract address
|
|
100
|
+
const contractForView = new ethers.Contract(
|
|
101
|
+
contractAddress,
|
|
102
|
+
[
|
|
103
|
+
"function eip712Domain() public view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions)",
|
|
104
|
+
"function decimals() public view returns (uint8)",
|
|
105
|
+
"function nonces(address owner) public view returns (uint256)",
|
|
106
|
+
],
|
|
107
|
+
provider,
|
|
108
|
+
);
|
|
109
|
+
// domain
|
|
110
|
+
const eip712Domain = await contractForView.eip712Domain();
|
|
111
|
+
const domain = {
|
|
112
|
+
name: eip712Domain.name, // domain name
|
|
113
|
+
version: eip712Domain.version, // domain version
|
|
114
|
+
verifyingContract: eip712Domain.verifyingContract, // contract address
|
|
115
|
+
chainId: eip712Domain.chainId, // chain ID
|
|
116
|
+
};
|
|
117
|
+
// types and value for permit
|
|
118
|
+
const TYPES = {
|
|
119
|
+
Permit: [
|
|
120
|
+
{ name: "owner", type: "address" },
|
|
121
|
+
{ name: "spender", type: "address" },
|
|
122
|
+
{ name: "value", type: "uint256" },
|
|
123
|
+
{ name: "nonce", type: "uint256" },
|
|
124
|
+
{ name: "deadline", type: "uint256" },
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
// value for permit
|
|
128
|
+
const owner = await signer.getAddress();
|
|
129
|
+
const nonce = await contractForView.nonces(owner);
|
|
130
|
+
const decimals = await contractForView.decimals();
|
|
131
|
+
const spender = "<target Ethereum address>"; // Replace with the actual target Ethereum address
|
|
132
|
+
const value = {
|
|
133
|
+
owner: owner,
|
|
134
|
+
spender: spender,
|
|
135
|
+
value: ethers.parseUnits("1", decimals),
|
|
136
|
+
nonce: nonce,
|
|
137
|
+
deadline: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
|
|
138
|
+
};
|
|
139
|
+
// sign typed data
|
|
140
|
+
const signature = await signer.signTypedData(domain, TYPES, value);
|
|
141
|
+
const sign = ethers.Signature.from(signature);
|
|
142
|
+
// send permit transaction
|
|
143
|
+
const contract = new ethers.Contract(
|
|
144
|
+
contractAddress,
|
|
145
|
+
[
|
|
146
|
+
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public",
|
|
147
|
+
],
|
|
148
|
+
otherConnectedSigner,
|
|
149
|
+
);
|
|
150
|
+
const tx = await contract.permit(
|
|
151
|
+
value.owner,
|
|
152
|
+
value.spender,
|
|
153
|
+
value.value,
|
|
154
|
+
value.deadline,
|
|
155
|
+
sign.v,
|
|
156
|
+
sign.r,
|
|
157
|
+
sign.s,
|
|
158
|
+
);
|
|
159
|
+
const receipt = await tx.wait();
|
|
160
|
+
console.log(
|
|
161
|
+
"Permit Transaction:",
|
|
162
|
+
receipt?.status === 1 ? "Success" : "Failure",
|
|
163
|
+
);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### authorize
|
|
167
|
+
|
|
168
|
+
Example: EIP-7702: Set Code for EOAs
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const delegateContractAddress = "<>target delegate contract address>"; // Replace with the actual target delegate contract address
|
|
172
|
+
|
|
173
|
+
// address
|
|
174
|
+
const address = await connectedSigner.getAddress();
|
|
175
|
+
// code
|
|
176
|
+
const code = await ethers.provider.getCode(address);
|
|
177
|
+
if (code === "0x") {
|
|
178
|
+
// nonce
|
|
179
|
+
const nonce = await connectedSigner.getNonce();
|
|
180
|
+
// authorize
|
|
181
|
+
const auth = await connectedSigner.authorize({
|
|
182
|
+
address: delegateContractAddress,
|
|
183
|
+
nonce: nonce + 1,
|
|
184
|
+
});
|
|
185
|
+
// send transaction with authorization
|
|
186
|
+
const tx = await connectedSigner.sendTransaction({
|
|
187
|
+
to: address,
|
|
188
|
+
type: 4,
|
|
189
|
+
authorizationList: [auth],
|
|
190
|
+
});
|
|
191
|
+
const receipt = await tx.wait();
|
|
192
|
+
console.log(
|
|
193
|
+
"Authorization Transaction:",
|
|
194
|
+
receipt?.status === 1 ? "Success" : "Failure",
|
|
195
|
+
);
|
|
196
|
+
} else {
|
|
197
|
+
console.log("There is already code at this address.");
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Prerequisites
|
|
202
|
+
|
|
203
|
+
- AWS KMS key
|
|
204
|
+
- Key spec
|
|
205
|
+
- ECC_SECG_P256K1 (secp256k1)
|
|
206
|
+
- Action
|
|
207
|
+
- kms:Sign
|
|
208
|
+
- kms:GetPublicKey
|
|
209
|
+
|
|
210
|
+
## Constructor
|
|
211
|
+
|
|
212
|
+
`new AwsKmsSigner(keyId, config?, provider?)`
|
|
213
|
+
|
|
214
|
+
Creates a new AwsKmsSigner instance.
|
|
215
|
+
|
|
216
|
+
- `keyId`: AWS KMS Key ID or ARN
|
|
217
|
+
- `config`: Optional AWS KMS client configuration
|
|
218
|
+
- `provider`: Optional ethers.js Provider
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { KMSClientConfig } from "@aws-sdk/client-kms";
|
|
2
|
+
import { AbstractSigner, Authorization, AuthorizationRequest, Provider, Signer, TransactionRequest, TypedDataDomain, TypedDataField } from "ethers";
|
|
3
|
+
/**
|
|
4
|
+
* A Signer implementation that uses AWS KMS to sign messages and transactions.
|
|
5
|
+
*
|
|
6
|
+
* The signer retrieves the public key from AWS KMS to compute the Ethereum address
|
|
7
|
+
*/
|
|
8
|
+
export declare class AwsKmsSigner extends AbstractSigner {
|
|
9
|
+
private keyId;
|
|
10
|
+
private config;
|
|
11
|
+
private kmsClient;
|
|
12
|
+
address: string;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new AwsKmsSigner instance.
|
|
15
|
+
*
|
|
16
|
+
* @param keyId - The AWS KMS Key ID or ARN to use for signing
|
|
17
|
+
* @param config - Optional AWS KMS client configuration
|
|
18
|
+
* @param provider - Optional ethers.js Provider to use for resolving ENS names and addresses
|
|
19
|
+
*/
|
|
20
|
+
constructor(keyId: string, config?: KMSClientConfig, provider?: Provider);
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves the Ethereum address associated with the AWS KMS key. This is derived from the public key retrieved from AWS KMS. The address is cached after the first retrieval for efficiency.
|
|
23
|
+
*
|
|
24
|
+
* @returns A promise that resolves to the Ethereum address as a string
|
|
25
|
+
*/
|
|
26
|
+
getAddress(): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Connects the signer to a provider.
|
|
29
|
+
*
|
|
30
|
+
* @param provider - An ethers.js Provider to connect to
|
|
31
|
+
* @returns A new Signer instance connected to the provided provider
|
|
32
|
+
*
|
|
33
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L71
|
|
34
|
+
*/
|
|
35
|
+
connect(provider: Provider): Signer;
|
|
36
|
+
/**
|
|
37
|
+
* Signs a transaction with the AWS KMS key.
|
|
38
|
+
*
|
|
39
|
+
* @param tx - The transaction to sign
|
|
40
|
+
* @returns A promise that resolves to the signed transaction as a string
|
|
41
|
+
*
|
|
42
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L75
|
|
43
|
+
*/
|
|
44
|
+
signTransaction(tx: TransactionRequest): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Signs a message with the AWS KMS key.
|
|
47
|
+
*
|
|
48
|
+
* @param message - The message to sign, which can be a string or a Uint8Array
|
|
49
|
+
* @returns A promise that resolves to the signed message as a string
|
|
50
|
+
*
|
|
51
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L109
|
|
52
|
+
*/
|
|
53
|
+
signMessage(message: string | Uint8Array): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Signs an authorization request with the AWS KMS key. The authorization request is first resolved to ensure that any ENS names are converted to addresses, and then the resulting data is hashed and signed.
|
|
56
|
+
*
|
|
57
|
+
* @param auth - The authorization request to sign, which includes the address, nonce, and chainId
|
|
58
|
+
* @returns A promise that resolves to the signed authorization, which includes the address, nonce, chainId, and signature
|
|
59
|
+
*
|
|
60
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L116
|
|
61
|
+
*/
|
|
62
|
+
authorize(auth: AuthorizationRequest): Promise<Authorization>;
|
|
63
|
+
/**
|
|
64
|
+
* Signs typed data with the AWS KMS key. The typed data is first resolved to ensure that any ENS names are converted to addresses, and then the resulting data is hashed and signed.
|
|
65
|
+
*
|
|
66
|
+
* @param domain - The domain separator for the typed data, which includes the name, version, chainId, and verifyingContract
|
|
67
|
+
* @param types - The type definitions for the typed data, which is a mapping of type names to arrays of field definitions
|
|
68
|
+
* @param value - The actual data to sign, which is a mapping of field names to values
|
|
69
|
+
* @returns A promise that resolves to the signed typed data as a string
|
|
70
|
+
*
|
|
71
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L138
|
|
72
|
+
*/
|
|
73
|
+
signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
|
|
74
|
+
/**
|
|
75
|
+
* Internal method to sign a digest with the AWS KMS key.
|
|
76
|
+
* This method sends a SignCommand to AWS KMS with the specified digest and retrieves the signature. The signature is then parsed from ASN.1 format and converted to the format expected by Ethereum, including handling low S values and computing the recovery parameter (v) based on the recovered address.
|
|
77
|
+
*
|
|
78
|
+
* @param digest - The digest to sign, which must be a 32-byte value (e.g., the hash of a message or transaction)
|
|
79
|
+
* @returns A promise that resolves to the signature in the format expected by Ethereum, including r, s, and v components
|
|
80
|
+
*/
|
|
81
|
+
private _sign;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EACL,cAAc,EAGd,aAAa,EACb,oBAAoB,EAWpB,QAAQ,EAMR,MAAM,EAKN,kBAAkB,EAClB,eAAe,EAEf,cAAc,EACf,MAAM,QAAQ,CAAC;AAEhB;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,cAAc;IAE9C,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,SAAS,CAAY;IAE7B,OAAO,EAAG,MAAM,CAAC;IAEjB;;;;;;OAMG;gBACS,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,QAAQ;IAOxE;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAiCnC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;IAInC;;;;;;;OAOG;IACG,eAAe,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;IAiC9D;;;;;;;OAOG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE;;;;;;;OAOG;IACG,SAAS,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAyBnE;;;;;;;;;OASG;IACG,aAAa,CACjB,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,EAI5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC,MAAM,CAAC;IAoClB;;;;;;OAMG;YACW,KAAK;CA2DpB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { KMSClient, GetPublicKeyCommand, SignCommand, } from "@aws-sdk/client-kms";
|
|
2
|
+
import { ECDSASigValue } from "@peculiar/asn1-ecc";
|
|
3
|
+
import { AsnConvert } from "@peculiar/asn1-schema";
|
|
4
|
+
import { SubjectPublicKeyInfo } from "@peculiar/asn1-x509";
|
|
5
|
+
import { AbstractSigner, assert, assertArgument, copyRequest, dataLength, getAddress, getBigInt, getBytes, hashAuthorization, hashMessage, keccak256, N, recoverAddress, resolveAddress, resolveProperties, Signature, toBeHex, toBigInt, Transaction, TypedDataEncoder, } from "ethers";
|
|
6
|
+
/**
|
|
7
|
+
* A Signer implementation that uses AWS KMS to sign messages and transactions.
|
|
8
|
+
*
|
|
9
|
+
* The signer retrieves the public key from AWS KMS to compute the Ethereum address
|
|
10
|
+
*/
|
|
11
|
+
export class AwsKmsSigner extends AbstractSigner {
|
|
12
|
+
// AWS KMS Key ID or ARN
|
|
13
|
+
keyId;
|
|
14
|
+
// AWS KMS client configuration
|
|
15
|
+
config;
|
|
16
|
+
// AWS KMS client instance
|
|
17
|
+
kmsClient;
|
|
18
|
+
// Cached Ethereum address derived from the KMS public key
|
|
19
|
+
address;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new AwsKmsSigner instance.
|
|
22
|
+
*
|
|
23
|
+
* @param keyId - The AWS KMS Key ID or ARN to use for signing
|
|
24
|
+
* @param config - Optional AWS KMS client configuration
|
|
25
|
+
* @param provider - Optional ethers.js Provider to use for resolving ENS names and addresses
|
|
26
|
+
*/
|
|
27
|
+
constructor(keyId, config, provider) {
|
|
28
|
+
super(provider);
|
|
29
|
+
this.keyId = keyId;
|
|
30
|
+
this.config = config || {};
|
|
31
|
+
this.kmsClient = new KMSClient(this.config);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves the Ethereum address associated with the AWS KMS key. This is derived from the public key retrieved from AWS KMS. The address is cached after the first retrieval for efficiency.
|
|
35
|
+
*
|
|
36
|
+
* @returns A promise that resolves to the Ethereum address as a string
|
|
37
|
+
*/
|
|
38
|
+
async getAddress() {
|
|
39
|
+
// If the address is already cached, return it
|
|
40
|
+
if (!this.address) {
|
|
41
|
+
// Retrieve the public key from AWS KMS
|
|
42
|
+
const command = new GetPublicKeyCommand({
|
|
43
|
+
KeyId: this.keyId,
|
|
44
|
+
});
|
|
45
|
+
// Send the command to AWS KMS and get the response
|
|
46
|
+
const response = await this.kmsClient.send(command);
|
|
47
|
+
// Extract the public key from the response
|
|
48
|
+
const publicKey = response.PublicKey;
|
|
49
|
+
// If the public key is not available, throw an error
|
|
50
|
+
if (!publicKey) {
|
|
51
|
+
throw new Error("Failed to retrieve public key from AWS KMS");
|
|
52
|
+
}
|
|
53
|
+
// Parse the public key using ASN.1 to extract the EC public key
|
|
54
|
+
const ecPublicKey = AsnConvert.parse(Buffer.from(publicKey), SubjectPublicKeyInfo).subjectPublicKey;
|
|
55
|
+
// Compute the Ethereum address by taking the keccak256 hash of the public key (excluding the first byte) and taking the last 20 bytes of the hash
|
|
56
|
+
// https://ethereum.github.io/yellowpaper/paper.pdf - Appendix F. Signing Transactions - Ethereum address A(pr) (a 160-bit value)
|
|
57
|
+
// https://eips.ethereum.org/EIPS/eip-55 - Ethereum address checksum
|
|
58
|
+
this.address = getAddress("0x" +
|
|
59
|
+
keccak256(new Uint8Array(ecPublicKey.slice(1, ecPublicKey.byteLength))).slice(-40));
|
|
60
|
+
}
|
|
61
|
+
return this.address;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Connects the signer to a provider.
|
|
65
|
+
*
|
|
66
|
+
* @param provider - An ethers.js Provider to connect to
|
|
67
|
+
* @returns A new Signer instance connected to the provided provider
|
|
68
|
+
*
|
|
69
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L71
|
|
70
|
+
*/
|
|
71
|
+
connect(provider) {
|
|
72
|
+
return new AwsKmsSigner(this.keyId, this.config, provider);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Signs a transaction with the AWS KMS key.
|
|
76
|
+
*
|
|
77
|
+
* @param tx - The transaction to sign
|
|
78
|
+
* @returns A promise that resolves to the signed transaction as a string
|
|
79
|
+
*
|
|
80
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L75
|
|
81
|
+
*/
|
|
82
|
+
async signTransaction(tx) {
|
|
83
|
+
tx = copyRequest(tx);
|
|
84
|
+
// Replace any Addressable or ENS name with an address
|
|
85
|
+
const { to, from } = await resolveProperties({
|
|
86
|
+
to: tx.to ? resolveAddress(tx.to, this) : undefined,
|
|
87
|
+
from: tx.from ? resolveAddress(tx.from, this) : undefined,
|
|
88
|
+
});
|
|
89
|
+
if (to != null) {
|
|
90
|
+
tx.to = to;
|
|
91
|
+
}
|
|
92
|
+
if (from != null) {
|
|
93
|
+
tx.from = from;
|
|
94
|
+
}
|
|
95
|
+
if (tx.from != null) {
|
|
96
|
+
assertArgument(getAddress(tx.from) === (await this.getAddress()), "transaction from address mismatch", "tx.from", tx.from);
|
|
97
|
+
delete tx.from;
|
|
98
|
+
}
|
|
99
|
+
// Build the transaction
|
|
100
|
+
const btx = Transaction.from(tx);
|
|
101
|
+
btx.signature = await this._sign(btx.unsignedHash);
|
|
102
|
+
return btx.serialized;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Signs a message with the AWS KMS key.
|
|
106
|
+
*
|
|
107
|
+
* @param message - The message to sign, which can be a string or a Uint8Array
|
|
108
|
+
* @returns A promise that resolves to the signed message as a string
|
|
109
|
+
*
|
|
110
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L109
|
|
111
|
+
*/
|
|
112
|
+
async signMessage(message) {
|
|
113
|
+
return (await this._sign(hashMessage(message))).serialized;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Signs an authorization request with the AWS KMS key. The authorization request is first resolved to ensure that any ENS names are converted to addresses, and then the resulting data is hashed and signed.
|
|
117
|
+
*
|
|
118
|
+
* @param auth - The authorization request to sign, which includes the address, nonce, and chainId
|
|
119
|
+
* @returns A promise that resolves to the signed authorization, which includes the address, nonce, chainId, and signature
|
|
120
|
+
*
|
|
121
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L116
|
|
122
|
+
*/
|
|
123
|
+
async authorize(auth) {
|
|
124
|
+
auth = Object.assign({}, auth, {
|
|
125
|
+
address: await resolveAddress(auth.address, this),
|
|
126
|
+
});
|
|
127
|
+
auth = await this.populateAuthorization(auth);
|
|
128
|
+
assertArgument(typeof auth.address === "string", "invalid address for authorizeSync", "auth.address", auth);
|
|
129
|
+
const signature = await this._sign(hashAuthorization(auth));
|
|
130
|
+
return Object.assign({}, {
|
|
131
|
+
address: getAddress(auth.address),
|
|
132
|
+
nonce: getBigInt(auth.nonce || 0),
|
|
133
|
+
chainId: getBigInt(auth.chainId || 0),
|
|
134
|
+
}, { signature });
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Signs typed data with the AWS KMS key. The typed data is first resolved to ensure that any ENS names are converted to addresses, and then the resulting data is hashed and signed.
|
|
138
|
+
*
|
|
139
|
+
* @param domain - The domain separator for the typed data, which includes the name, version, chainId, and verifyingContract
|
|
140
|
+
* @param types - The type definitions for the typed data, which is a mapping of type names to arrays of field definitions
|
|
141
|
+
* @param value - The actual data to sign, which is a mapping of field names to values
|
|
142
|
+
* @returns A promise that resolves to the signed typed data as a string
|
|
143
|
+
*
|
|
144
|
+
* @note https://github.com/ethers-io/ethers.js/blob/b746c3cf6cd191e2357fa55751696676ffda060e/src.ts/wallet/base-wallet.ts#L138
|
|
145
|
+
*/
|
|
146
|
+
async signTypedData(domain, types,
|
|
147
|
+
// `ethers` typings use `any` here for the value mapping.
|
|
148
|
+
// This is intentional and matches the abstract signer interface, so we suppress the lint warning.
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
|
+
value) {
|
|
151
|
+
// Populate any ENS names
|
|
152
|
+
const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (name) => {
|
|
153
|
+
// @TODO: this should use resolveName; addresses don't
|
|
154
|
+
// need a provider
|
|
155
|
+
assert(this.provider != null, "cannot resolve ENS names without a provider", "UNSUPPORTED_OPERATION", {
|
|
156
|
+
operation: "resolveName",
|
|
157
|
+
info: { name },
|
|
158
|
+
});
|
|
159
|
+
const address = await this.provider.resolveName(name);
|
|
160
|
+
assert(address != null, "unconfigured ENS name", "UNCONFIGURED_NAME", {
|
|
161
|
+
value: name,
|
|
162
|
+
});
|
|
163
|
+
return address;
|
|
164
|
+
});
|
|
165
|
+
return (await this._sign(TypedDataEncoder.hash(populated.domain, types, populated.value))).serialized;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Internal method to sign a digest with the AWS KMS key.
|
|
169
|
+
* This method sends a SignCommand to AWS KMS with the specified digest and retrieves the signature. The signature is then parsed from ASN.1 format and converted to the format expected by Ethereum, including handling low S values and computing the recovery parameter (v) based on the recovered address.
|
|
170
|
+
*
|
|
171
|
+
* @param digest - The digest to sign, which must be a 32-byte value (e.g., the hash of a message or transaction)
|
|
172
|
+
* @returns A promise that resolves to the signature in the format expected by Ethereum, including r, s, and v components
|
|
173
|
+
*/
|
|
174
|
+
async _sign(digest) {
|
|
175
|
+
assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
|
|
176
|
+
// Send the SignCommand to AWS KMS with the specified digest and signing parameters
|
|
177
|
+
const command = new SignCommand({
|
|
178
|
+
KeyId: this.keyId,
|
|
179
|
+
Message: getBytes(digest),
|
|
180
|
+
SigningAlgorithm: "ECDSA_SHA_256",
|
|
181
|
+
MessageType: "DIGEST",
|
|
182
|
+
});
|
|
183
|
+
// Retrieve the signature from AWS KMS
|
|
184
|
+
const response = await this.kmsClient.send(command);
|
|
185
|
+
const signature = response.Signature;
|
|
186
|
+
// If the signature is not available, throw an error
|
|
187
|
+
if (!signature) {
|
|
188
|
+
throw new Error("Failed to sign message with AWS KMS");
|
|
189
|
+
}
|
|
190
|
+
// Parse the signature from ASN.1 format to extract the r and s values
|
|
191
|
+
const ecdsaSig = AsnConvert.parse(Buffer.from(signature), ECDSASigValue);
|
|
192
|
+
// Handle low S values by ensuring that s is less than or equal to N/2.
|
|
193
|
+
// If s is greater than N/2, it is replaced with N - s to ensure that the signature is in canonical form, which is required by Ethereum.
|
|
194
|
+
// https://ethereum.github.io/yellowpaper/paper.pdf - Appendix F. Signing Transactions
|
|
195
|
+
let s = toBigInt(new Uint8Array(ecdsaSig.s));
|
|
196
|
+
const HALF = N >> 1n;
|
|
197
|
+
if (s > HALF) {
|
|
198
|
+
s = N - s;
|
|
199
|
+
}
|
|
200
|
+
// Construct the signature object with r, s, and a default v value of 0x1b (27 in decimal).
|
|
201
|
+
// The r and s values are converted to hexadecimal format with appropriate padding.
|
|
202
|
+
const sig = {
|
|
203
|
+
r: toBeHex(toBigInt(new Uint8Array(ecdsaSig.r))),
|
|
204
|
+
s: toBeHex(s, 32),
|
|
205
|
+
v: 0x1b,
|
|
206
|
+
};
|
|
207
|
+
// Compute the recovery parameter (v) by recovering the address from the signature and comparing it to the signer's address. If they do not match, set v to 0x1c.
|
|
208
|
+
const recover = recoverAddress(digest, {
|
|
209
|
+
r: sig.r,
|
|
210
|
+
s: sig.s,
|
|
211
|
+
v: sig.v,
|
|
212
|
+
});
|
|
213
|
+
// Retrieve the signer's address from AWS KMS (this will be cached after the first retrieval)
|
|
214
|
+
const address = await this.getAddress();
|
|
215
|
+
// If the recovered address does not match the signer's address, set v to 0x1c (28 in decimal) to indicate that the signature is valid but the recovery parameter is different.
|
|
216
|
+
if (address.toLowerCase() !== recover.toLowerCase()) {
|
|
217
|
+
sig.v = 0x1c;
|
|
218
|
+
}
|
|
219
|
+
return Signature.from(sig);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tnaka-dev/aws-kms-ethers-v6-signer",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "A signer implementation for ethers.js v6 that uses AWS Key Management Service (KMS) for secure cryptographic signing operations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"test:coverage": "jest --coverage",
|
|
13
|
+
"lint": "eslint src --ext .ts",
|
|
14
|
+
"build": "tsc"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/tnakagawa/aws-kms-ethers-v6-signer.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": "Takatoshi Nakagawa",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/tnakagawa/aws-kms-ethers-v6-signer/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/tnakagawa/aws-kms-ethers-v6-signer#readme",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@eslint/js": "^10.0.1",
|
|
30
|
+
"@types/jest": "^30.0.0",
|
|
31
|
+
"@types/node": "^25.5.0",
|
|
32
|
+
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
|
33
|
+
"@typescript-eslint/parser": "^8.57.0",
|
|
34
|
+
"eslint": "^10.0.3",
|
|
35
|
+
"eslint-plugin-jest": "^29.15.0",
|
|
36
|
+
"globals": "^17.4.0",
|
|
37
|
+
"jest": "^30.3.0",
|
|
38
|
+
"jiti": "^2.6.1",
|
|
39
|
+
"ts-jest": "^29.4.6",
|
|
40
|
+
"ts-node": "^10.9.2",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"typescript-eslint": "^8.57.0",
|
|
43
|
+
"asn1js": "^3.0.7",
|
|
44
|
+
"aws-sdk-client-mock": "^4.1.0",
|
|
45
|
+
"pkijs": "^3.3.3"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@aws-sdk/client-kms": "^3.1009.0",
|
|
49
|
+
"@peculiar/asn1-ecc": "^2.6.1",
|
|
50
|
+
"@peculiar/asn1-schema": "^2.6.0",
|
|
51
|
+
"@peculiar/asn1-x509": "^2.6.1",
|
|
52
|
+
"ethers": "^6.16.0"
|
|
53
|
+
}
|
|
54
|
+
}
|