@phantom/indexed-db-stamper 1.0.0 → 1.0.3
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/dist/index.d.ts +9 -2
- package/dist/index.js +33 -11
- package/dist/index.mjs +33 -11
- package/package.json +6 -5
package/dist/index.d.ts
CHANGED
|
@@ -13,8 +13,13 @@ type IndexedDbStamperConfig = {
|
|
|
13
13
|
* IndexedDB-based key manager that stores cryptographic keys securely in IndexedDB
|
|
14
14
|
* and performs signing operations without ever exposing private key material.
|
|
15
15
|
*
|
|
16
|
+
* Algorithm selection:
|
|
17
|
+
* - Prefers Ed25519 for maximum security and performance
|
|
18
|
+
* - Automatically falls back to ECDSA P-256 (secp256r1) on browsers that don't support Ed25519
|
|
19
|
+
* (e.g., older Android WebViews before Chrome 113)
|
|
20
|
+
*
|
|
16
21
|
* Security model:
|
|
17
|
-
* - Generates non-extractable
|
|
22
|
+
* - Generates non-extractable keypairs using Web Crypto API
|
|
18
23
|
* - Stores keys entirely within Web Crypto API secure context
|
|
19
24
|
* - Private keys NEVER exist in JavaScript memory
|
|
20
25
|
* - Provides signing methods without exposing private keys
|
|
@@ -33,9 +38,11 @@ declare class IndexedDbStamper implements StamperWithKeyManagement {
|
|
|
33
38
|
salt?: string;
|
|
34
39
|
constructor(config?: IndexedDbStamperConfig);
|
|
35
40
|
/**
|
|
36
|
-
* Initialize the stamper by opening IndexedDB and retrieving or generating keys
|
|
41
|
+
* Initialize the stamper by opening IndexedDB and retrieving or generating keys.
|
|
42
|
+
* Automatically selects the best supported algorithm.
|
|
37
43
|
*/
|
|
38
44
|
init(): Promise<StamperKeyInfo>;
|
|
45
|
+
private getSupportedAlgorithm;
|
|
39
46
|
/**
|
|
40
47
|
* Get the public key information
|
|
41
48
|
*/
|
package/dist/index.js
CHANGED
|
@@ -34,16 +34,26 @@ __export(src_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(src_exports);
|
|
36
36
|
var import_base64url = require("@phantom/base64url");
|
|
37
|
+
var import_constants = require("@phantom/constants");
|
|
37
38
|
var import_bs58 = __toESM(require("bs58"));
|
|
38
39
|
var import_sdk_types = require("@phantom/sdk-types");
|
|
40
|
+
var WEB_CRYPTO_ALGORITHM_CONFIGS = {
|
|
41
|
+
[import_constants.DEFAULT_AUTHENTICATOR_ALGORITHM]: {
|
|
42
|
+
generateParams: { name: "Ed25519" },
|
|
43
|
+
signParams: { name: "Ed25519" }
|
|
44
|
+
},
|
|
45
|
+
[import_sdk_types.Algorithm.secp256r1]: {
|
|
46
|
+
generateParams: { name: "ECDSA", namedCurve: "P-256" },
|
|
47
|
+
signParams: { name: "ECDSA", hash: "SHA-256" }
|
|
48
|
+
}
|
|
49
|
+
};
|
|
39
50
|
var IndexedDbStamper = class {
|
|
40
51
|
// Optional for PKI, required for OIDC
|
|
41
52
|
constructor(config = {}) {
|
|
42
53
|
this.db = null;
|
|
43
54
|
this.activeKeyPairRecord = null;
|
|
44
55
|
this.pendingKeyPairRecord = null;
|
|
45
|
-
this.algorithm =
|
|
46
|
-
// Use Ed25519 for maximum security and performance
|
|
56
|
+
this.algorithm = import_constants.DEFAULT_AUTHENTICATOR_ALGORITHM;
|
|
47
57
|
// The type of stamper, can be changed at any time
|
|
48
58
|
this.type = "PKI";
|
|
49
59
|
if (typeof window === "undefined" || !window.indexedDB) {
|
|
@@ -57,17 +67,34 @@ var IndexedDbStamper = class {
|
|
|
57
67
|
this.salt = config.salt;
|
|
58
68
|
}
|
|
59
69
|
/**
|
|
60
|
-
* Initialize the stamper by opening IndexedDB and retrieving or generating keys
|
|
70
|
+
* Initialize the stamper by opening IndexedDB and retrieving or generating keys.
|
|
71
|
+
* Automatically selects the best supported algorithm.
|
|
61
72
|
*/
|
|
62
73
|
async init() {
|
|
63
74
|
await this.openDB();
|
|
64
75
|
this.activeKeyPairRecord = await this.loadActiveKeyPairRecord();
|
|
65
|
-
if (
|
|
76
|
+
if (this.activeKeyPairRecord) {
|
|
77
|
+
this.algorithm = this.activeKeyPairRecord.keyPair.privateKey.algorithm.name === "Ed25519" ? import_sdk_types.Algorithm.ed25519 : import_sdk_types.Algorithm.secp256r1;
|
|
78
|
+
} else {
|
|
79
|
+
this.algorithm = await this.getSupportedAlgorithm();
|
|
66
80
|
this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
|
|
67
81
|
}
|
|
68
82
|
this.pendingKeyPairRecord = await this.loadPendingKeyPairRecord();
|
|
69
83
|
return this.activeKeyPairRecord.keyInfo;
|
|
70
84
|
}
|
|
85
|
+
async getSupportedAlgorithm() {
|
|
86
|
+
for (const [algorithm, params] of Object.entries(WEB_CRYPTO_ALGORITHM_CONFIGS)) {
|
|
87
|
+
try {
|
|
88
|
+
await crypto.subtle.generateKey(params.generateParams, false, ["sign", "verify"]);
|
|
89
|
+
return algorithm;
|
|
90
|
+
} catch {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(
|
|
95
|
+
"Your browser does not support the encryption needed for secure authentication. Please use a different browser or upgrade to a supported browser."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
71
98
|
/**
|
|
72
99
|
* Get the public key information
|
|
73
100
|
*/
|
|
@@ -95,10 +122,7 @@ var IndexedDbStamper = class {
|
|
|
95
122
|
}
|
|
96
123
|
const dataBytes = new Uint8Array(data);
|
|
97
124
|
const signature = await crypto.subtle.sign(
|
|
98
|
-
|
|
99
|
-
name: this.algorithm,
|
|
100
|
-
hash: "SHA-256"
|
|
101
|
-
},
|
|
125
|
+
WEB_CRYPTO_ALGORITHM_CONFIGS[this.algorithm].signParams,
|
|
102
126
|
this.activeKeyPairRecord.keyPair.privateKey,
|
|
103
127
|
dataBytes
|
|
104
128
|
);
|
|
@@ -210,9 +234,7 @@ var IndexedDbStamper = class {
|
|
|
210
234
|
}
|
|
211
235
|
async generateAndStoreNewKeyPair(type) {
|
|
212
236
|
const keyPair = await crypto.subtle.generateKey(
|
|
213
|
-
|
|
214
|
-
name: "Ed25519"
|
|
215
|
-
},
|
|
237
|
+
WEB_CRYPTO_ALGORITHM_CONFIGS[this.algorithm].generateParams,
|
|
216
238
|
false,
|
|
217
239
|
// non-extractable - private key can never be exported
|
|
218
240
|
["sign", "verify"]
|
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { base64urlEncode } from "@phantom/base64url";
|
|
3
|
+
import { DEFAULT_AUTHENTICATOR_ALGORITHM } from "@phantom/constants";
|
|
3
4
|
import bs58 from "bs58";
|
|
4
5
|
import { Algorithm } from "@phantom/sdk-types";
|
|
6
|
+
var WEB_CRYPTO_ALGORITHM_CONFIGS = {
|
|
7
|
+
[DEFAULT_AUTHENTICATOR_ALGORITHM]: {
|
|
8
|
+
generateParams: { name: "Ed25519" },
|
|
9
|
+
signParams: { name: "Ed25519" }
|
|
10
|
+
},
|
|
11
|
+
[Algorithm.secp256r1]: {
|
|
12
|
+
generateParams: { name: "ECDSA", namedCurve: "P-256" },
|
|
13
|
+
signParams: { name: "ECDSA", hash: "SHA-256" }
|
|
14
|
+
}
|
|
15
|
+
};
|
|
5
16
|
var IndexedDbStamper = class {
|
|
6
17
|
// Optional for PKI, required for OIDC
|
|
7
18
|
constructor(config = {}) {
|
|
8
19
|
this.db = null;
|
|
9
20
|
this.activeKeyPairRecord = null;
|
|
10
21
|
this.pendingKeyPairRecord = null;
|
|
11
|
-
this.algorithm =
|
|
12
|
-
// Use Ed25519 for maximum security and performance
|
|
22
|
+
this.algorithm = DEFAULT_AUTHENTICATOR_ALGORITHM;
|
|
13
23
|
// The type of stamper, can be changed at any time
|
|
14
24
|
this.type = "PKI";
|
|
15
25
|
if (typeof window === "undefined" || !window.indexedDB) {
|
|
@@ -23,17 +33,34 @@ var IndexedDbStamper = class {
|
|
|
23
33
|
this.salt = config.salt;
|
|
24
34
|
}
|
|
25
35
|
/**
|
|
26
|
-
* Initialize the stamper by opening IndexedDB and retrieving or generating keys
|
|
36
|
+
* Initialize the stamper by opening IndexedDB and retrieving or generating keys.
|
|
37
|
+
* Automatically selects the best supported algorithm.
|
|
27
38
|
*/
|
|
28
39
|
async init() {
|
|
29
40
|
await this.openDB();
|
|
30
41
|
this.activeKeyPairRecord = await this.loadActiveKeyPairRecord();
|
|
31
|
-
if (
|
|
42
|
+
if (this.activeKeyPairRecord) {
|
|
43
|
+
this.algorithm = this.activeKeyPairRecord.keyPair.privateKey.algorithm.name === "Ed25519" ? Algorithm.ed25519 : Algorithm.secp256r1;
|
|
44
|
+
} else {
|
|
45
|
+
this.algorithm = await this.getSupportedAlgorithm();
|
|
32
46
|
this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
|
|
33
47
|
}
|
|
34
48
|
this.pendingKeyPairRecord = await this.loadPendingKeyPairRecord();
|
|
35
49
|
return this.activeKeyPairRecord.keyInfo;
|
|
36
50
|
}
|
|
51
|
+
async getSupportedAlgorithm() {
|
|
52
|
+
for (const [algorithm, params] of Object.entries(WEB_CRYPTO_ALGORITHM_CONFIGS)) {
|
|
53
|
+
try {
|
|
54
|
+
await crypto.subtle.generateKey(params.generateParams, false, ["sign", "verify"]);
|
|
55
|
+
return algorithm;
|
|
56
|
+
} catch {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
throw new Error(
|
|
61
|
+
"Your browser does not support the encryption needed for secure authentication. Please use a different browser or upgrade to a supported browser."
|
|
62
|
+
);
|
|
63
|
+
}
|
|
37
64
|
/**
|
|
38
65
|
* Get the public key information
|
|
39
66
|
*/
|
|
@@ -61,10 +88,7 @@ var IndexedDbStamper = class {
|
|
|
61
88
|
}
|
|
62
89
|
const dataBytes = new Uint8Array(data);
|
|
63
90
|
const signature = await crypto.subtle.sign(
|
|
64
|
-
|
|
65
|
-
name: this.algorithm,
|
|
66
|
-
hash: "SHA-256"
|
|
67
|
-
},
|
|
91
|
+
WEB_CRYPTO_ALGORITHM_CONFIGS[this.algorithm].signParams,
|
|
68
92
|
this.activeKeyPairRecord.keyPair.privateKey,
|
|
69
93
|
dataBytes
|
|
70
94
|
);
|
|
@@ -176,9 +200,7 @@ var IndexedDbStamper = class {
|
|
|
176
200
|
}
|
|
177
201
|
async generateAndStoreNewKeyPair(type) {
|
|
178
202
|
const keyPair = await crypto.subtle.generateKey(
|
|
179
|
-
|
|
180
|
-
name: "Ed25519"
|
|
181
|
-
},
|
|
203
|
+
WEB_CRYPTO_ALGORITHM_CONFIGS[this.algorithm].generateParams,
|
|
182
204
|
false,
|
|
183
205
|
// non-extractable - private key can never be exported
|
|
184
206
|
["sign", "verify"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/indexed-db-stamper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "IndexedDB stamper for Phantom Wallet SDK with non-extractable key storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,10 +44,11 @@
|
|
|
44
44
|
"typescript": "^5.0.4"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@phantom/base64url": "^1.0.
|
|
48
|
-
"@phantom/
|
|
49
|
-
"@phantom/
|
|
50
|
-
"@phantom/
|
|
47
|
+
"@phantom/base64url": "^1.0.3",
|
|
48
|
+
"@phantom/constants": "^1.0.3",
|
|
49
|
+
"@phantom/crypto": "^1.0.3",
|
|
50
|
+
"@phantom/embedded-provider-core": "^1.0.3",
|
|
51
|
+
"@phantom/sdk-types": "^1.0.3",
|
|
51
52
|
"bs58": "^6.0.0",
|
|
52
53
|
"buffer": "^6.0.3"
|
|
53
54
|
},
|