@stoex/wallet-crypto 0.1.0

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,37 @@
1
+ /**
2
+ * AES-256-GCM 암호화
3
+ * @param plaintext - 암호화할 평문 (개인키 등)
4
+ * @param keyHex - 32바이트 마스터 키 (64자 hex 문자열)
5
+ * @returns 저장 가능한 암호화 문자열 "iv:authTag:encrypted"
6
+ */
7
+ declare function encryptKey(plaintext: string, keyHex: string): string;
8
+ /**
9
+ * AES-256-GCM 복호화
10
+ * @param stored - encryptKey()의 반환값 "iv:authTag:encrypted"
11
+ * @param keyHex - 32바이트 마스터 키 (64자 hex)
12
+ * @returns 복호화된 평문
13
+ */
14
+ declare function decryptKey(stored: string, keyHex: string): string;
15
+ /**
16
+ * 랜덤 32바이트 마스터 키 생성 (hex 문자열)
17
+ * 최초 설정 시 1회 생성 후 환경변수에 저장.
18
+ */
19
+ declare function generateMasterKey(): string;
20
+ /**
21
+ * EVM 지갑 생성
22
+ * @returns privateKey (0x...), address (0x...)
23
+ */
24
+ declare function generateWallet(): {
25
+ privateKey: `0x${string}`;
26
+ address: `0x${string}`;
27
+ };
28
+ /**
29
+ * 지갑 생성 + 개인키 즉시 암호화
30
+ * DB 저장용 원스텝 헬퍼
31
+ */
32
+ declare function generateAndEncryptWallet(keyHex: string): {
33
+ address: `0x${string}`;
34
+ privkey_enc: string;
35
+ };
36
+
37
+ export { decryptKey, encryptKey, generateAndEncryptWallet, generateMasterKey, generateWallet };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * AES-256-GCM 암호화
3
+ * @param plaintext - 암호화할 평문 (개인키 등)
4
+ * @param keyHex - 32바이트 마스터 키 (64자 hex 문자열)
5
+ * @returns 저장 가능한 암호화 문자열 "iv:authTag:encrypted"
6
+ */
7
+ declare function encryptKey(plaintext: string, keyHex: string): string;
8
+ /**
9
+ * AES-256-GCM 복호화
10
+ * @param stored - encryptKey()의 반환값 "iv:authTag:encrypted"
11
+ * @param keyHex - 32바이트 마스터 키 (64자 hex)
12
+ * @returns 복호화된 평문
13
+ */
14
+ declare function decryptKey(stored: string, keyHex: string): string;
15
+ /**
16
+ * 랜덤 32바이트 마스터 키 생성 (hex 문자열)
17
+ * 최초 설정 시 1회 생성 후 환경변수에 저장.
18
+ */
19
+ declare function generateMasterKey(): string;
20
+ /**
21
+ * EVM 지갑 생성
22
+ * @returns privateKey (0x...), address (0x...)
23
+ */
24
+ declare function generateWallet(): {
25
+ privateKey: `0x${string}`;
26
+ address: `0x${string}`;
27
+ };
28
+ /**
29
+ * 지갑 생성 + 개인키 즉시 암호화
30
+ * DB 저장용 원스텝 헬퍼
31
+ */
32
+ declare function generateAndEncryptWallet(keyHex: string): {
33
+ address: `0x${string}`;
34
+ privkey_enc: string;
35
+ };
36
+
37
+ export { decryptKey, encryptKey, generateAndEncryptWallet, generateMasterKey, generateWallet };
package/dist/index.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ decryptKey: () => decryptKey,
24
+ encryptKey: () => encryptKey,
25
+ generateAndEncryptWallet: () => generateAndEncryptWallet,
26
+ generateMasterKey: () => generateMasterKey,
27
+ generateWallet: () => generateWallet
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var import_crypto = require("crypto");
31
+ var import_accounts = require("viem/accounts");
32
+ var ALGO = "aes-256-gcm";
33
+ function encryptKey(plaintext, keyHex) {
34
+ if (!keyHex || keyHex.length < 64) {
35
+ throw new Error("keyHex\uB294 32\uBC14\uC774\uD2B8(64\uC790 hex)\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
36
+ }
37
+ const key = Buffer.from(keyHex, "hex");
38
+ const iv = (0, import_crypto.randomBytes)(12);
39
+ const cipher = (0, import_crypto.createCipheriv)(ALGO, key, iv);
40
+ const encrypted = Buffer.concat([
41
+ cipher.update(plaintext, "utf8"),
42
+ cipher.final()
43
+ ]);
44
+ const authTag = cipher.getAuthTag();
45
+ return [
46
+ iv.toString("hex"),
47
+ authTag.toString("hex"),
48
+ encrypted.toString("hex")
49
+ ].join(":");
50
+ }
51
+ function decryptKey(stored, keyHex) {
52
+ if (!keyHex || keyHex.length < 64) {
53
+ throw new Error("keyHex\uB294 32\uBC14\uC774\uD2B8(64\uC790 hex)\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
54
+ }
55
+ const [ivHex, authTagHex, encHex] = stored.split(":");
56
+ if (!ivHex || !authTagHex || !encHex) {
57
+ throw new Error("\uC798\uBABB\uB41C \uC554\uD638\uD654 \uD615\uC2DD \u2014 encryptKey() \uCD9C\uB825\uAC12\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694");
58
+ }
59
+ const key = Buffer.from(keyHex, "hex");
60
+ const decipher = (0, import_crypto.createDecipheriv)(ALGO, key, Buffer.from(ivHex, "hex"));
61
+ decipher.setAuthTag(Buffer.from(authTagHex, "hex"));
62
+ return Buffer.concat([
63
+ decipher.update(Buffer.from(encHex, "hex")),
64
+ decipher.final()
65
+ ]).toString("utf8");
66
+ }
67
+ function generateMasterKey() {
68
+ return (0, import_crypto.randomBytes)(32).toString("hex");
69
+ }
70
+ function generateWallet() {
71
+ const privateKey = (0, import_accounts.generatePrivateKey)();
72
+ const address = (0, import_accounts.privateKeyToAddress)(privateKey);
73
+ return { privateKey, address };
74
+ }
75
+ function generateAndEncryptWallet(keyHex) {
76
+ const { privateKey, address } = generateWallet();
77
+ const privkey_enc = encryptKey(privateKey, keyHex);
78
+ return { address, privkey_enc };
79
+ }
80
+ // Annotate the CommonJS export names for ESM import in node:
81
+ 0 && (module.exports = {
82
+ decryptKey,
83
+ encryptKey,
84
+ generateAndEncryptWallet,
85
+ generateMasterKey,
86
+ generateWallet
87
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,58 @@
1
+ // src/index.ts
2
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
3
+ import { generatePrivateKey, privateKeyToAddress } from "viem/accounts";
4
+ var ALGO = "aes-256-gcm";
5
+ function encryptKey(plaintext, keyHex) {
6
+ if (!keyHex || keyHex.length < 64) {
7
+ throw new Error("keyHex\uB294 32\uBC14\uC774\uD2B8(64\uC790 hex)\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
8
+ }
9
+ const key = Buffer.from(keyHex, "hex");
10
+ const iv = randomBytes(12);
11
+ const cipher = createCipheriv(ALGO, key, iv);
12
+ const encrypted = Buffer.concat([
13
+ cipher.update(plaintext, "utf8"),
14
+ cipher.final()
15
+ ]);
16
+ const authTag = cipher.getAuthTag();
17
+ return [
18
+ iv.toString("hex"),
19
+ authTag.toString("hex"),
20
+ encrypted.toString("hex")
21
+ ].join(":");
22
+ }
23
+ function decryptKey(stored, keyHex) {
24
+ if (!keyHex || keyHex.length < 64) {
25
+ throw new Error("keyHex\uB294 32\uBC14\uC774\uD2B8(64\uC790 hex)\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4");
26
+ }
27
+ const [ivHex, authTagHex, encHex] = stored.split(":");
28
+ if (!ivHex || !authTagHex || !encHex) {
29
+ throw new Error("\uC798\uBABB\uB41C \uC554\uD638\uD654 \uD615\uC2DD \u2014 encryptKey() \uCD9C\uB825\uAC12\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694");
30
+ }
31
+ const key = Buffer.from(keyHex, "hex");
32
+ const decipher = createDecipheriv(ALGO, key, Buffer.from(ivHex, "hex"));
33
+ decipher.setAuthTag(Buffer.from(authTagHex, "hex"));
34
+ return Buffer.concat([
35
+ decipher.update(Buffer.from(encHex, "hex")),
36
+ decipher.final()
37
+ ]).toString("utf8");
38
+ }
39
+ function generateMasterKey() {
40
+ return randomBytes(32).toString("hex");
41
+ }
42
+ function generateWallet() {
43
+ const privateKey = generatePrivateKey();
44
+ const address = privateKeyToAddress(privateKey);
45
+ return { privateKey, address };
46
+ }
47
+ function generateAndEncryptWallet(keyHex) {
48
+ const { privateKey, address } = generateWallet();
49
+ const privkey_enc = encryptKey(privateKey, keyHex);
50
+ return { address, privkey_enc };
51
+ }
52
+ export {
53
+ decryptKey,
54
+ encryptKey,
55
+ generateAndEncryptWallet,
56
+ generateMasterKey,
57
+ generateWallet
58
+ };
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@stoex/wallet-crypto",
3
+ "version": "0.1.0",
4
+ "description": "AES-256-GCM private key encryption and ETH wallet generation for custody services",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": ["dist", "src"],
16
+ "scripts": {
17
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean --tsconfig tsconfig.json",
18
+ "dev": "tsup src/index.ts --format esm,cjs --dts --watch --tsconfig tsconfig.json"
19
+ },
20
+ "keywords": ["wallet", "custody", "aes-gcm", "encryption", "ethereum", "evm"],
21
+ "license": "MIT",
22
+ "peerDependencies": {
23
+ "viem": ">=2"
24
+ },
25
+ "devDependencies": {
26
+ "tsup": "^8",
27
+ "typescript": "^5"
28
+ }
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,92 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
2
+ import { generatePrivateKey, privateKeyToAddress } from "viem/accounts";
3
+
4
+ const ALGO = "aes-256-gcm";
5
+
6
+ // 저장 형식: iv(24자 hex) + ":" + authTag(32자 hex) + ":" + encrypted(hex)
7
+
8
+ /**
9
+ * AES-256-GCM 암호화
10
+ * @param plaintext - 암호화할 평문 (개인키 등)
11
+ * @param keyHex - 32바이트 마스터 키 (64자 hex 문자열)
12
+ * @returns 저장 가능한 암호화 문자열 "iv:authTag:encrypted"
13
+ */
14
+ export function encryptKey(plaintext: string, keyHex: string): string {
15
+ if (!keyHex || keyHex.length < 64) {
16
+ throw new Error("keyHex는 32바이트(64자 hex)가 필요합니다");
17
+ }
18
+ const key = Buffer.from(keyHex, "hex");
19
+ const iv = randomBytes(12); // GCM 표준 96-bit IV
20
+
21
+ const cipher = createCipheriv(ALGO, key, iv);
22
+ const encrypted = Buffer.concat([
23
+ cipher.update(plaintext, "utf8"),
24
+ cipher.final(),
25
+ ]);
26
+ const authTag = cipher.getAuthTag();
27
+
28
+ return [
29
+ iv.toString("hex"),
30
+ authTag.toString("hex"),
31
+ encrypted.toString("hex"),
32
+ ].join(":");
33
+ }
34
+
35
+ /**
36
+ * AES-256-GCM 복호화
37
+ * @param stored - encryptKey()의 반환값 "iv:authTag:encrypted"
38
+ * @param keyHex - 32바이트 마스터 키 (64자 hex)
39
+ * @returns 복호화된 평문
40
+ */
41
+ export function decryptKey(stored: string, keyHex: string): string {
42
+ if (!keyHex || keyHex.length < 64) {
43
+ throw new Error("keyHex는 32바이트(64자 hex)가 필요합니다");
44
+ }
45
+ const [ivHex, authTagHex, encHex] = stored.split(":");
46
+ if (!ivHex || !authTagHex || !encHex) {
47
+ throw new Error("잘못된 암호화 형식 — encryptKey() 출력값만 사용하세요");
48
+ }
49
+
50
+ const key = Buffer.from(keyHex, "hex");
51
+ const decipher = createDecipheriv(ALGO, key, Buffer.from(ivHex, "hex"));
52
+ decipher.setAuthTag(Buffer.from(authTagHex, "hex"));
53
+
54
+ return Buffer.concat([
55
+ decipher.update(Buffer.from(encHex, "hex")),
56
+ decipher.final(),
57
+ ]).toString("utf8");
58
+ }
59
+
60
+ /**
61
+ * 랜덤 32바이트 마스터 키 생성 (hex 문자열)
62
+ * 최초 설정 시 1회 생성 후 환경변수에 저장.
63
+ */
64
+ export function generateMasterKey(): string {
65
+ return randomBytes(32).toString("hex");
66
+ }
67
+
68
+ /**
69
+ * EVM 지갑 생성
70
+ * @returns privateKey (0x...), address (0x...)
71
+ */
72
+ export function generateWallet(): {
73
+ privateKey: `0x${string}`;
74
+ address: `0x${string}`;
75
+ } {
76
+ const privateKey = generatePrivateKey();
77
+ const address = privateKeyToAddress(privateKey);
78
+ return { privateKey, address };
79
+ }
80
+
81
+ /**
82
+ * 지갑 생성 + 개인키 즉시 암호화
83
+ * DB 저장용 원스텝 헬퍼
84
+ */
85
+ export function generateAndEncryptWallet(keyHex: string): {
86
+ address: `0x${string}`;
87
+ privkey_enc: string;
88
+ } {
89
+ const { privateKey, address } = generateWallet();
90
+ const privkey_enc = encryptKey(privateKey, keyHex);
91
+ return { address, privkey_enc };
92
+ }