@yume-chan/adb-credential-web 2.1.0 → 3.0.0-beta.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.
- package/LICENSE +1 -1
- package/README.md +4 -1
- package/esm/index.d.ts +2 -23
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -102
- package/esm/index.js.map +1 -1
- package/esm/manager.d.ts +9 -0
- package/esm/manager.d.ts.map +1 -0
- package/esm/manager.js +56 -0
- package/esm/manager.js.map +1 -0
- package/esm/storage/index.d.ts +6 -0
- package/esm/storage/index.d.ts.map +1 -0
- package/esm/storage/index.js +6 -0
- package/esm/storage/index.js.map +1 -0
- package/esm/storage/indexed-db/index.d.ts +3 -0
- package/esm/storage/indexed-db/index.d.ts.map +1 -0
- package/esm/storage/indexed-db/index.js +3 -0
- package/esm/storage/indexed-db/index.js.map +1 -0
- package/esm/storage/indexed-db/shared.d.ts +4 -0
- package/esm/storage/indexed-db/shared.d.ts.map +1 -0
- package/esm/storage/indexed-db/shared.js +50 -0
- package/esm/storage/indexed-db/shared.js.map +1 -0
- package/esm/storage/indexed-db/v1.d.ts +5 -0
- package/esm/storage/indexed-db/v1.d.ts.map +1 -0
- package/esm/storage/indexed-db/v1.js +22 -0
- package/esm/storage/indexed-db/v1.js.map +1 -0
- package/esm/storage/indexed-db/v2.d.ts +14 -0
- package/esm/storage/indexed-db/v2.d.ts.map +1 -0
- package/esm/storage/indexed-db/v2.js +78 -0
- package/esm/storage/indexed-db/v2.js.map +1 -0
- package/esm/storage/local-storage.d.ts +8 -0
- package/esm/storage/local-storage.d.ts.map +1 -0
- package/esm/storage/local-storage.js +25 -0
- package/esm/storage/local-storage.js.map +1 -0
- package/esm/storage/password.d.ts +27 -0
- package/esm/storage/password.d.ts.map +1 -0
- package/esm/storage/password.js +129 -0
- package/esm/storage/password.js.map +1 -0
- package/esm/storage/prf/index.d.ts +4 -0
- package/esm/storage/prf/index.d.ts.map +1 -0
- package/esm/storage/prf/index.js +4 -0
- package/esm/storage/prf/index.js.map +1 -0
- package/esm/storage/prf/source.d.ts +27 -0
- package/esm/storage/prf/source.d.ts.map +1 -0
- package/esm/storage/prf/source.js +2 -0
- package/esm/storage/prf/source.js.map +1 -0
- package/esm/storage/prf/storage.d.ts +19 -0
- package/esm/storage/prf/storage.d.ts.map +1 -0
- package/esm/storage/prf/storage.js +125 -0
- package/esm/storage/prf/storage.js.map +1 -0
- package/esm/storage/prf/web-authn.d.ts +55 -0
- package/esm/storage/prf/web-authn.d.ts.map +1 -0
- package/esm/storage/prf/web-authn.js +138 -0
- package/esm/storage/prf/web-authn.js.map +1 -0
- package/esm/storage/type.d.ts +11 -0
- package/esm/storage/type.d.ts.map +1 -0
- package/esm/storage/type.js +2 -0
- package/esm/storage/type.js.map +1 -0
- package/package.json +8 -5
- package/src/index.ts +2 -121
- package/src/manager.ts +82 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/indexed-db/index.ts +2 -0
- package/src/storage/indexed-db/shared.ts +62 -0
- package/src/storage/indexed-db/v1.ts +29 -0
- package/src/storage/indexed-db/v2.ts +95 -0
- package/src/storage/local-storage.ts +37 -0
- package/src/storage/password.ts +245 -0
- package/src/storage/prf/index.ts +3 -0
- package/src/storage/prf/source.ts +35 -0
- package/src/storage/prf/storage.ts +191 -0
- package/src/storage/prf/web-authn.ts +175 -0
- package/src/storage/type.ts +18 -0
- package/CHANGELOG.md +0 -149
- package/tsconfig.build.tsbuildinfo +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
<a href="https://tangoadb.dev/discord">
|
|
25
25
|
<img alt="Discord" src="https://img.shields.io/discord/1120215514732564502?logo=discord&logoColor=%23ffffff&label=Discord">
|
|
26
26
|
</a>
|
|
27
|
+
<a href="https://tangoadb.dev/wechat">
|
|
28
|
+
<img alt="WeChat Group" src="https://img.shields.io/badge/WeChat-Group-%2307C160?logo=wechat&logoColor=white">
|
|
29
|
+
</a>
|
|
27
30
|
</p>
|
|
28
31
|
|
|
29
32
|
This package is part of [Tango ADB](https://github.com/yume-chan/ya-webadb). Generally you need multiple packages to build a complete ADB client that can run on Web browsers and Node.js. Read the documentation for more information.
|
|
@@ -34,7 +37,7 @@ Check the latest documentation at https://tangoadb.dev/tango/daemon/credential-s
|
|
|
34
37
|
|
|
35
38
|
## Sponsors
|
|
36
39
|
|
|
37
|
-
[Become a backer](https://opencollective.com/ya-webadb) and get your image on our README on
|
|
40
|
+
[Become a backer](https://opencollective.com/ya-webadb) and get your image on our README on GitHub with a link to your site.
|
|
38
41
|
|
|
39
42
|
<a href="https://opencollective.com/ya-webadb/backer/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/0/avatar.svg?requireActive=false"></a>
|
|
40
43
|
<a href="https://opencollective.com/ya-webadb/backer/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/1/avatar.svg?requireActive=false"></a>
|
package/esm/index.d.ts
CHANGED
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* An `AdbCredentialStore` implementation that creates RSA private keys using Web Crypto API
|
|
4
|
-
* and stores them in IndexedDB.
|
|
5
|
-
*/
|
|
6
|
-
export default class AdbWebCredentialStore implements AdbCredentialStore {
|
|
7
|
-
#private;
|
|
8
|
-
constructor(appName?: string);
|
|
9
|
-
/**
|
|
10
|
-
* Generates a RSA private key and store it into LocalStorage.
|
|
11
|
-
*
|
|
12
|
-
* Calling this method multiple times will overwrite the previous key.
|
|
13
|
-
*
|
|
14
|
-
* @returns The private key in PKCS #8 format.
|
|
15
|
-
*/
|
|
16
|
-
generateKey(): Promise<AdbPrivateKey>;
|
|
17
|
-
/**
|
|
18
|
-
* Yields the stored RSA private key.
|
|
19
|
-
*
|
|
20
|
-
* This method returns a generator, so `for await...of...` loop should be used to read the key.
|
|
21
|
-
*/
|
|
22
|
-
iterateKeys(): AsyncGenerator<AdbPrivateKey, void, void>;
|
|
23
|
-
}
|
|
1
|
+
export * from "./manager.js";
|
|
2
|
+
export * from "./storage/index.js";
|
|
24
3
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
|
package/esm/index.js
CHANGED
|
@@ -1,103 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return new Promise((resolve, reject) => {
|
|
4
|
-
const request = indexedDB.open("Tango", 1);
|
|
5
|
-
request.onerror = () => {
|
|
6
|
-
reject(request.error);
|
|
7
|
-
};
|
|
8
|
-
request.onupgradeneeded = () => {
|
|
9
|
-
const db = request.result;
|
|
10
|
-
db.createObjectStore("Authentication", { autoIncrement: true });
|
|
11
|
-
};
|
|
12
|
-
request.onsuccess = () => {
|
|
13
|
-
const db = request.result;
|
|
14
|
-
resolve(db);
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
async function saveKey(key) {
|
|
19
|
-
const db = await openDatabase();
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
const transaction = db.transaction("Authentication", "readwrite");
|
|
22
|
-
const store = transaction.objectStore("Authentication");
|
|
23
|
-
const putRequest = store.add(key);
|
|
24
|
-
putRequest.onerror = () => {
|
|
25
|
-
reject(putRequest.error);
|
|
26
|
-
};
|
|
27
|
-
putRequest.onsuccess = () => {
|
|
28
|
-
resolve();
|
|
29
|
-
};
|
|
30
|
-
transaction.onerror = () => {
|
|
31
|
-
reject(transaction.error);
|
|
32
|
-
};
|
|
33
|
-
transaction.oncomplete = () => {
|
|
34
|
-
db.close();
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
async function getAllKeys() {
|
|
39
|
-
const db = await openDatabase();
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
const transaction = db.transaction("Authentication", "readonly");
|
|
42
|
-
const store = transaction.objectStore("Authentication");
|
|
43
|
-
const getRequest = store.getAll();
|
|
44
|
-
getRequest.onerror = () => {
|
|
45
|
-
reject(getRequest.error);
|
|
46
|
-
};
|
|
47
|
-
getRequest.onsuccess = () => {
|
|
48
|
-
resolve(getRequest.result);
|
|
49
|
-
};
|
|
50
|
-
transaction.onerror = () => {
|
|
51
|
-
reject(transaction.error);
|
|
52
|
-
};
|
|
53
|
-
transaction.oncomplete = () => {
|
|
54
|
-
db.close();
|
|
55
|
-
};
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* An `AdbCredentialStore` implementation that creates RSA private keys using Web Crypto API
|
|
60
|
-
* and stores them in IndexedDB.
|
|
61
|
-
*/
|
|
62
|
-
export default class AdbWebCredentialStore {
|
|
63
|
-
#appName;
|
|
64
|
-
constructor(appName = "Tango") {
|
|
65
|
-
this.#appName = appName;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Generates a RSA private key and store it into LocalStorage.
|
|
69
|
-
*
|
|
70
|
-
* Calling this method multiple times will overwrite the previous key.
|
|
71
|
-
*
|
|
72
|
-
* @returns The private key in PKCS #8 format.
|
|
73
|
-
*/
|
|
74
|
-
async generateKey() {
|
|
75
|
-
const { privateKey: cryptoKey } = await crypto.subtle.generateKey({
|
|
76
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
77
|
-
modulusLength: 2048,
|
|
78
|
-
// 65537
|
|
79
|
-
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
80
|
-
hash: "SHA-1",
|
|
81
|
-
}, true, ["sign", "verify"]);
|
|
82
|
-
const privateKey = new Uint8Array(await crypto.subtle.exportKey("pkcs8", cryptoKey));
|
|
83
|
-
await saveKey(privateKey);
|
|
84
|
-
return {
|
|
85
|
-
buffer: privateKey,
|
|
86
|
-
name: `${this.#appName}@${globalThis.location.hostname}`,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Yields the stored RSA private key.
|
|
91
|
-
*
|
|
92
|
-
* This method returns a generator, so `for await...of...` loop should be used to read the key.
|
|
93
|
-
*/
|
|
94
|
-
async *iterateKeys() {
|
|
95
|
-
for (const key of await getAllKeys()) {
|
|
96
|
-
yield {
|
|
97
|
-
buffer: key,
|
|
98
|
-
name: `${this.#appName}@${globalThis.location.hostname}`,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
1
|
+
export * from "./manager.js";
|
|
2
|
+
export * from "./storage/index.js";
|
|
103
3
|
//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
|
package/esm/manager.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AdbCredentialManager, AdbPrivateKey, MaybeError } from "@yume-chan/adb";
|
|
2
|
+
import type { TangoKeyStorage } from "./storage/index.js";
|
|
3
|
+
export declare class AdbWebCryptoCredentialManager implements AdbCredentialManager {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(storage: TangoKeyStorage, name?: string);
|
|
6
|
+
generateKey(): Promise<AdbPrivateKey>;
|
|
7
|
+
iterateKeys(): AsyncGenerator<MaybeError<AdbPrivateKey>, void, void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,oBAAoB,EACpB,aAAa,EACb,UAAU,EACb,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,qBAAa,6BAA8B,YAAW,oBAAoB;;gBAK1D,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,MAAM;IAK7C,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAsCpC,WAAW,IAAI,cAAc,CAChC,UAAU,CAAC,aAAa,CAAC,EACzB,IAAI,EACJ,IAAI,CACP;CAoBJ"}
|
package/esm/manager.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { rsaParsePrivateKey } from "@yume-chan/adb";
|
|
2
|
+
export class AdbWebCryptoCredentialManager {
|
|
3
|
+
#storage;
|
|
4
|
+
#name;
|
|
5
|
+
constructor(storage, name) {
|
|
6
|
+
this.#storage = storage;
|
|
7
|
+
this.#name = name;
|
|
8
|
+
}
|
|
9
|
+
async generateKey() {
|
|
10
|
+
// NOTE: ADB public key authentication doesn't use standard
|
|
11
|
+
// RSASSA-PKCS1-v1_5 algorithm to sign and verify data.
|
|
12
|
+
// We implemented ADB public key authentication ourselves in core package,
|
|
13
|
+
// so some parameters for Web Crypto API are not used.
|
|
14
|
+
const { privateKey: cryptoKey } = await crypto.subtle.generateKey({
|
|
15
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
16
|
+
modulusLength: 2048,
|
|
17
|
+
// 65537
|
|
18
|
+
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
|
19
|
+
// Not used
|
|
20
|
+
hash: "SHA-1",
|
|
21
|
+
}, true,
|
|
22
|
+
// Not used
|
|
23
|
+
["sign"]);
|
|
24
|
+
const privateKey = new Uint8Array(await crypto.subtle.exportKey("pkcs8", cryptoKey));
|
|
25
|
+
const parsed = rsaParsePrivateKey(privateKey);
|
|
26
|
+
await this.#storage.save(privateKey, this.#name);
|
|
27
|
+
// Clear secret memory
|
|
28
|
+
// * `privateKey` is not allowed to be used after `save`
|
|
29
|
+
privateKey.fill(0);
|
|
30
|
+
return {
|
|
31
|
+
...parsed,
|
|
32
|
+
name: this.#name,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async *iterateKeys() {
|
|
36
|
+
for await (const result of this.#storage.load()) {
|
|
37
|
+
if (result instanceof Error) {
|
|
38
|
+
yield result;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// `privateKey` is owned by `#storage` and will be cleared by it
|
|
43
|
+
yield {
|
|
44
|
+
...rsaParsePrivateKey(result.privateKey),
|
|
45
|
+
name: result.name ?? this.#name,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
yield e instanceof Error
|
|
50
|
+
? e
|
|
51
|
+
: new Error(String(e), { cause: e });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAIpD,MAAM,OAAO,6BAA6B;IAC7B,QAAQ,CAAkB;IAE1B,KAAK,CAAqB;IAEnC,YAAY,OAAwB,EAAE,IAAa;QAC/C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,WAAW;QACb,2DAA2D;QAC3D,uDAAuD;QACvD,0EAA0E;QAC1E,sDAAsD;QAEtD,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAC7D;YACI,IAAI,EAAE,mBAAmB;YACzB,aAAa,EAAE,IAAI;YACnB,QAAQ;YACR,cAAc,EAAE,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,WAAW;YACX,IAAI,EAAE,OAAO;SAChB,EACD,IAAI;QACJ,WAAW;QACX,CAAC,MAAM,CAAC,CACX,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,UAAU,CAC7B,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CACpD,CAAC;QAEF,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAE9C,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjD,sBAAsB;QACtB,0DAA0D;QAC1D,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnB,OAAO;YACH,GAAG,MAAM;YACT,IAAI,EAAE,IAAI,CAAC,KAAK;SACnB,CAAC;IACN,CAAC;IAED,KAAK,CAAC,CAAC,WAAW;QAKd,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9C,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;gBAC1B,MAAM,MAAM,CAAC;gBACb,SAAS;YACb,CAAC;YAED,IAAI,CAAC;gBACD,gEAAgE;gBAChE,MAAM;oBACF,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC;oBACxC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK;iBAClC,CAAC;YACN,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,MAAM,CAAC,YAAY,KAAK;oBACpB,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/indexed-db/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/indexed-db/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function waitRequest<T>(request: IDBRequest<T>): Promise<T>;
|
|
2
|
+
export declare function openDatabase(name: string, version: number, onUpgrade: (db: IDBDatabase) => undefined): Promise<IDBDatabase>;
|
|
3
|
+
export declare function createTransaction<T>(database: IDBDatabase, storeName: string, callback: (transaction: IDBTransaction) => T): Promise<T>;
|
|
4
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/storage/indexed-db/shared.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASjE;AAED,wBAAsB,YAAY,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,SAAS,GAC1C,OAAO,CAAC,WAAW,CAAC,CAStB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAC/B,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CA+BZ"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function waitRequest(request) {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
request.onerror = () => {
|
|
4
|
+
reject(request.error);
|
|
5
|
+
};
|
|
6
|
+
request.onsuccess = () => {
|
|
7
|
+
resolve(request.result);
|
|
8
|
+
};
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export async function openDatabase(name, version, onUpgrade) {
|
|
12
|
+
const request = indexedDB.open(name, version);
|
|
13
|
+
request.onupgradeneeded = () => {
|
|
14
|
+
const db = request.result;
|
|
15
|
+
onUpgrade(db);
|
|
16
|
+
};
|
|
17
|
+
return await waitRequest(request);
|
|
18
|
+
}
|
|
19
|
+
export function createTransaction(database, storeName, callback) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const transaction = database.transaction(storeName, "readwrite");
|
|
22
|
+
transaction.onerror = () => {
|
|
23
|
+
reject(transaction.error);
|
|
24
|
+
};
|
|
25
|
+
let result;
|
|
26
|
+
transaction.oncomplete = () => {
|
|
27
|
+
resolve(result);
|
|
28
|
+
};
|
|
29
|
+
transaction.onabort = () => {
|
|
30
|
+
reject(transaction.error ?? new Error("Transaction aborted"));
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
result = callback(transaction);
|
|
34
|
+
if (result instanceof Promise) {
|
|
35
|
+
throw new Error("callback must not be an async function");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
|
40
|
+
reject(e);
|
|
41
|
+
try {
|
|
42
|
+
transaction.abort();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/storage/indexed-db/shared.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAI,OAAsB;IACjD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE;YACnB,MAAM,CAAC,OAAO,CAAC,KAAM,CAAC,CAAC;QAC3B,CAAC,CAAC;QACF,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE;YACrB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAC9B,IAAY,EACZ,OAAe,EACf,SAAyC;IAEzC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE9C,OAAO,CAAC,eAAe,GAAG,GAAG,EAAE;QAC3B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAC1B,SAAS,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC7B,QAAqB,EACrB,SAAiB,EACjB,QAA4C;IAE5C,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACjE,WAAW,CAAC,OAAO,GAAG,GAAG,EAAE;YACvB,MAAM,CAAC,WAAW,CAAC,KAAM,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,IAAI,MAAU,CAAC;QACf,WAAW,CAAC,UAAU,GAAG,GAAG,EAAE;YAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC,CAAC;QACF,WAAW,CAAC,OAAO,GAAG,GAAG,EAAE;YACvB,MAAM,CAAC,WAAW,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC;QAEF,IAAI,CAAC;YACD,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC/B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC9D,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,2EAA2E;YAC3E,MAAM,CAAC,CAAC,CAAC,CAAC;YAEV,IAAI,CAAC;gBACD,WAAW,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACL,SAAS;YACb,CAAC;QACL,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const DefaultDatabaseName = "Tango";
|
|
2
|
+
export declare const DefaultStoreName = "Authentication";
|
|
3
|
+
export declare const Version1 = 1;
|
|
4
|
+
export declare function getAllKeysV1(): Promise<Uint8Array<ArrayBufferLike>[] | undefined>;
|
|
5
|
+
//# sourceMappingURL=v1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1.d.ts","sourceRoot":"","sources":["../../../src/storage/indexed-db/v1.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AACjD,eAAO,MAAM,QAAQ,IAAI,CAAC;AAE1B,wBAAsB,YAAY,uDAsBjC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createTransaction, openDatabase, waitRequest } from "./shared.js";
|
|
2
|
+
export const DefaultDatabaseName = "Tango";
|
|
3
|
+
export const DefaultStoreName = "Authentication";
|
|
4
|
+
export const Version1 = 1;
|
|
5
|
+
export async function getAllKeysV1() {
|
|
6
|
+
const databases = await indexedDB.databases();
|
|
7
|
+
if (databases.every((database) => database.name !== DefaultDatabaseName ||
|
|
8
|
+
database.version !== Version1)) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const db = await openDatabase(DefaultDatabaseName, Version1, () => { });
|
|
12
|
+
try {
|
|
13
|
+
return await createTransaction(db, DefaultStoreName, (tx) => {
|
|
14
|
+
const store = tx.objectStore(DefaultStoreName);
|
|
15
|
+
return waitRequest(store.getAll());
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
db.close();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=v1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1.js","sourceRoot":"","sources":["../../../src/storage/indexed-db/v1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAC3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AACjD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,YAAY;IAC9B,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,CAAC;IAC9C,IACI,SAAS,CAAC,KAAK,CACX,CAAC,QAAQ,EAAE,EAAE,CACT,QAAQ,CAAC,IAAI,KAAK,mBAAmB;QACrC,QAAQ,CAAC,OAAO,KAAK,QAAQ,CACpC,EACH,CAAC;QACC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,mBAAmB,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEvE,IAAI,CAAC;QACD,OAAO,MAAM,iBAAiB,CAAC,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE;YACxD,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;YAC/C,OAAO,WAAW,CAAC,KAAK,CAAC,MAAM,EAA8B,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACP,CAAC;YAAS,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TangoKey, TangoKeyStorage } from "../type.js";
|
|
2
|
+
export declare class TangoIndexedDbStorage implements TangoKeyStorage {
|
|
3
|
+
#private;
|
|
4
|
+
get databaseName(): string;
|
|
5
|
+
get storeName(): string;
|
|
6
|
+
constructor(options?: {
|
|
7
|
+
databaseName?: string;
|
|
8
|
+
storeName?: string;
|
|
9
|
+
});
|
|
10
|
+
save(privateKey: Uint8Array, name: string | undefined): Promise<undefined>;
|
|
11
|
+
load(): AsyncGenerator<TangoKey, void, void>;
|
|
12
|
+
clear(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=v2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../../src/storage/indexed-db/v2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO5D,qBAAa,qBAAsB,YAAW,eAAe;;IAEzD,IAAI,YAAY,WAEf;IAGD,IAAI,SAAS,WAEZ;gBAIW,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IA+B7D,IAAI,CACN,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAAC,SAAS,CAAC;IAad,IAAI,IAAI,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;IAe7C,KAAK;CAYd"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createTransaction, openDatabase, waitRequest } from "./shared.js";
|
|
2
|
+
import { DefaultDatabaseName, DefaultStoreName, getAllKeysV1 } from "./v1.js";
|
|
3
|
+
const Version = 2;
|
|
4
|
+
export class TangoIndexedDbStorage {
|
|
5
|
+
#databaseName;
|
|
6
|
+
get databaseName() {
|
|
7
|
+
return this.#databaseName;
|
|
8
|
+
}
|
|
9
|
+
#storeName;
|
|
10
|
+
get storeName() {
|
|
11
|
+
return this.#storeName;
|
|
12
|
+
}
|
|
13
|
+
#openDatabasePromise;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.#databaseName = options?.databaseName ?? DefaultDatabaseName;
|
|
16
|
+
this.#storeName = options?.storeName ?? DefaultStoreName;
|
|
17
|
+
}
|
|
18
|
+
async #openDatabaseCore() {
|
|
19
|
+
const v1Keys = await getAllKeysV1();
|
|
20
|
+
if (v1Keys) {
|
|
21
|
+
await waitRequest(indexedDB.deleteDatabase(DefaultDatabaseName));
|
|
22
|
+
}
|
|
23
|
+
return await openDatabase(this.#databaseName, Version, (db) => {
|
|
24
|
+
const store = db.createObjectStore(this.#storeName, {
|
|
25
|
+
autoIncrement: true,
|
|
26
|
+
});
|
|
27
|
+
if (v1Keys) {
|
|
28
|
+
for (const key of v1Keys) {
|
|
29
|
+
store.add({
|
|
30
|
+
privateKey: key,
|
|
31
|
+
name: undefined,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async #openDatabase() {
|
|
38
|
+
return (this.#openDatabasePromise ??= this.#openDatabaseCore());
|
|
39
|
+
}
|
|
40
|
+
async save(privateKey, name) {
|
|
41
|
+
const db = await this.#openDatabase();
|
|
42
|
+
try {
|
|
43
|
+
await createTransaction(db, this.#storeName, (tx) => {
|
|
44
|
+
const store = tx.objectStore(this.#storeName);
|
|
45
|
+
store.add({ privateKey, name });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
db.close();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async *load() {
|
|
53
|
+
const db = await this.#openDatabase();
|
|
54
|
+
try {
|
|
55
|
+
const keys = await createTransaction(db, this.#storeName, (tx) => {
|
|
56
|
+
const store = tx.objectStore(this.#storeName);
|
|
57
|
+
return waitRequest(store.getAll());
|
|
58
|
+
});
|
|
59
|
+
yield* keys;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
db.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async clear() {
|
|
66
|
+
const db = await this.#openDatabase();
|
|
67
|
+
try {
|
|
68
|
+
await createTransaction(db, this.#storeName, (tx) => {
|
|
69
|
+
const store = tx.objectStore(this.#storeName);
|
|
70
|
+
store.clear();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
db.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../../src/storage/indexed-db/v2.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE9E,MAAM,OAAO,GAAG,CAAC,CAAC;AAElB,MAAM,OAAO,qBAAqB;IACrB,aAAa,CAAS;IAC/B,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAEQ,UAAU,CAAS;IAC5B,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,oBAAoB,CAAmC;IAEvD,YAAY,OAAuD;QAC/D,IAAI,CAAC,aAAa,GAAG,OAAO,EAAE,YAAY,IAAI,mBAAmB,CAAC;QAClE,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,SAAS,IAAI,gBAAgB,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,iBAAiB;QACnB,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE;gBAChD,aAAa,EAAE,IAAI;aACtB,CAAC,CAAC;YAEH,IAAI,MAAM,EAAE,CAAC;gBACT,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;oBACvB,KAAK,CAAC,GAAG,CAAC;wBACN,UAAU,EAAE,GAAG;wBACf,IAAI,EAAE,SAAS;qBACC,CAAC,CAAC;gBAC1B,CAAC;YACL,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,aAAa;QACf,OAAO,CAAC,IAAI,CAAC,oBAAoB,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,IAAI,CACN,UAAsB,EACtB,IAAwB;QAExB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAEtC,IAAI,CAAC;YACD,MAAM,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE;gBAChD,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC9C,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAqB,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;QACP,CAAC;gBAAS,CAAC;YACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACL,CAAC;IAED,KAAK,CAAC,CAAC,IAAI;QACP,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAEtC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE;gBAC7D,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC9C,OAAO,WAAW,CAAC,KAAK,CAAC,MAAM,EAA4B,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,CAAC,IAAI,CAAC;QAChB,CAAC;gBAAS,CAAC;YACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAEtC,IAAI,CAAC;YACD,MAAM,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE;gBAChD,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC9C,KAAK,CAAC,KAAK,EAAE,CAAC;YAClB,CAAC,CAAC,CAAC;QACP,CAAC;gBAAS,CAAC;YACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TangoKey, TangoKeyStorage } from "./type.js";
|
|
2
|
+
export declare class TangoLocalStorage implements TangoKeyStorage {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(storageKey: string);
|
|
5
|
+
save(privateKey: Uint8Array, name: string | undefined): undefined;
|
|
6
|
+
load(): Generator<TangoKey, void, void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=local-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../../src/storage/local-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAQ3D,qBAAa,iBAAkB,YAAW,eAAe;;gBAGzC,UAAU,EAAE,MAAM;IAI9B,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAShE,IAAI,IAAI,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;CAU3C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { decodeBase64, decodeUtf8, encodeBase64 } from "@yume-chan/adb";
|
|
2
|
+
export class TangoLocalStorage {
|
|
3
|
+
#storageKey;
|
|
4
|
+
constructor(storageKey) {
|
|
5
|
+
this.#storageKey = storageKey;
|
|
6
|
+
}
|
|
7
|
+
save(privateKey, name) {
|
|
8
|
+
const json = JSON.stringify({
|
|
9
|
+
privateKey: decodeUtf8(encodeBase64(privateKey)),
|
|
10
|
+
name,
|
|
11
|
+
});
|
|
12
|
+
localStorage.setItem(this.#storageKey, json);
|
|
13
|
+
}
|
|
14
|
+
*load() {
|
|
15
|
+
const json = localStorage.getItem(this.#storageKey);
|
|
16
|
+
if (json) {
|
|
17
|
+
const { privateKey, name } = JSON.parse(json);
|
|
18
|
+
yield {
|
|
19
|
+
privateKey: decodeBase64(privateKey),
|
|
20
|
+
name,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=local-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.js","sourceRoot":"","sources":["../../src/storage/local-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAUxE,MAAM,OAAO,iBAAiB;IACjB,WAAW,CAAS;IAE7B,YAAY,UAAkB;QAC1B,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,UAAsB,EAAE,IAAwB;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YACxB,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI;SACgB,CAAC,CAAC;QAE1B,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,CAAC,IAAI;QACD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;YAC9D,MAAM;gBACF,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC;gBACpC,IAAI;aACP,CAAC;QACN,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MaybeError } from "@yume-chan/adb";
|
|
2
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
3
|
+
import type { TangoKey, TangoKeyStorage } from "./type.js";
|
|
4
|
+
declare class PasswordIncorrectError extends Error {
|
|
5
|
+
#private;
|
|
6
|
+
get keyName(): string | undefined;
|
|
7
|
+
constructor(keyName: string | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class TangoPasswordProtectedStorage implements TangoKeyStorage {
|
|
10
|
+
#private;
|
|
11
|
+
static PasswordIncorrectError: typeof PasswordIncorrectError;
|
|
12
|
+
constructor(options: {
|
|
13
|
+
storage: TangoKeyStorage;
|
|
14
|
+
requestPassword: TangoPasswordProtectedStorage.RequestPassword;
|
|
15
|
+
pbkdf2SaltLength?: number | undefined;
|
|
16
|
+
pbkdf2Iterations?: number | undefined;
|
|
17
|
+
aesIvLength?: number | undefined;
|
|
18
|
+
});
|
|
19
|
+
save(privateKey: Uint8Array, name: string | undefined): Promise<undefined>;
|
|
20
|
+
load(): AsyncGenerator<MaybeError<TangoKey>, void, void>;
|
|
21
|
+
}
|
|
22
|
+
export declare namespace TangoPasswordProtectedStorage {
|
|
23
|
+
type RequestPassword = (reason: "save" | "load", name: string | undefined) => MaybePromiseLike<string>;
|
|
24
|
+
type PasswordIncorrectError = typeof PasswordIncorrectError;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../src/storage/password.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAUzD,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA6D3D,cAAM,sBAAuB,SAAQ,KAAK;;IAEtC,IAAI,OAAO,uBAEV;gBAEW,OAAO,EAAE,MAAM,GAAG,SAAS;CAI1C;AAmBD,qBAAa,6BAA8B,YAAW,eAAe;;IACjE,MAAM,CAAC,sBAAsB,gCAA0B;gBAQ3C,OAAO,EAAE;QACjB,OAAO,EAAE,eAAe,CAAC;QACzB,eAAe,EAAE,6BAA6B,CAAC,eAAe,CAAC;QAC/D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACtC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACtC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACpC;IA6BK,IAAI,CACN,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAAC,SAAS,CAAC;IAgCd,IAAI,IAAI,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;CAsDlE;AAED,yBAAiB,6BAA6B,CAAC;IAC3C,KAAY,eAAe,GAAG,CAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,MAAM,GAAG,SAAS,KACvB,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAE9B,KAAY,sBAAsB,GAAG,OAAO,sBAAsB,CAAC;CACtE"}
|