feat: nip44
This commit is contained in:
parent
ecd957792d
commit
c2a3a706de
@ -160,7 +160,7 @@ export class NostrConnectWallet implements LNWallet {
|
||||
});
|
||||
const eb = new EventBuilder();
|
||||
eb.kind(23194 as EventKind)
|
||||
.content(await EventExt.encryptData(payload, this.#config.walletPubkey, this.#config.secret))
|
||||
.content(await EventExt.encryptDm(payload, this.#config.secret, this.#config.walletPubkey))
|
||||
.tag(["p", this.#config.walletPubkey]);
|
||||
|
||||
const evCommand = await eb.buildAndSign(this.#config.secret);
|
||||
@ -182,7 +182,7 @@ export class NostrConnectWallet implements LNWallet {
|
||||
return await new Promise<T>((resolve, reject) => {
|
||||
this.#commandQueue.set(evCommand.id, {
|
||||
resolve: async (o: string) => {
|
||||
const reply = JSON.parse(await EventExt.decryptData(o, this.#config.secret, this.#config.walletPubkey));
|
||||
const reply = JSON.parse(await EventExt.decryptDm(o, this.#config.secret, this.#config.walletPubkey));
|
||||
debug("NWC")("%o", reply);
|
||||
resolve(reply);
|
||||
},
|
||||
|
@ -17,6 +17,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@jest/globals": "^29.5.0",
|
||||
"@peculiar/webcrypto": "^1.4.3",
|
||||
"@types/jest": "^29.5.1",
|
||||
"jest": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
@ -25,7 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/curves": "^1.0.0",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@scure/base": "^1.1.1",
|
||||
"@stablelib/xchacha20": "^1.0.1",
|
||||
"bech32": "^2.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"uuid": "^9.0.0"
|
||||
|
@ -1,8 +1,9 @@
|
||||
import * as secp from "@noble/curves/secp256k1";
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
|
||||
import { EventKind, HexKey, NostrEvent } from ".";
|
||||
import base64 from "@protobufjs/base64";
|
||||
import { sha256, unixNow } from "./Utils";
|
||||
import { Nip4WebCryptoEncryptor } from "./impl/nip4";
|
||||
|
||||
export interface Tag {
|
||||
key: string
|
||||
@ -135,58 +136,15 @@ export abstract class EventExt {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the given message content
|
||||
*/
|
||||
static async encryptData(content: string, pubkey: HexKey, privkey: HexKey) {
|
||||
const key = await this.#getDmSharedKey(pubkey, privkey);
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const data = new TextEncoder().encode(content);
|
||||
const result = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
const uData = new Uint8Array(result);
|
||||
return `${base64.encode(uData, 0, result.byteLength)}?iv=${base64.encode(iv, 0, 16)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the content of the message
|
||||
*/
|
||||
static async decryptData(cyphertext: string, privkey: HexKey, pubkey: HexKey) {
|
||||
const key = await this.#getDmSharedKey(pubkey, privkey);
|
||||
const cSplit = cyphertext.split("?iv=");
|
||||
const data = new Uint8Array(base64.length(cSplit[0]));
|
||||
base64.decode(cSplit[0], data, 0);
|
||||
|
||||
const iv = new Uint8Array(base64.length(cSplit[1]));
|
||||
base64.decode(cSplit[1], iv, 0);
|
||||
|
||||
const result = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
return new TextDecoder().decode(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the content of this message in place
|
||||
*/
|
||||
static async decryptDm(content: string, privkey: HexKey, pubkey: HexKey) {
|
||||
return await this.decryptData(content, privkey, pubkey);
|
||||
const enc = new Nip4WebCryptoEncryptor();
|
||||
const key = enc.getSharedSecret(privkey, pubkey);
|
||||
return await enc.decryptData(content, key);
|
||||
}
|
||||
|
||||
static async #getDmSharedKey(pubkey: HexKey, privkey: HexKey) {
|
||||
const sharedPoint = secp.secp256k1.getSharedSecret(privkey, "02" + pubkey);
|
||||
const sharedX = sharedPoint.slice(1, 33);
|
||||
return await window.crypto.subtle.importKey("raw", sharedX, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
|
||||
static async encryptDm(content: string, privKey: HexKey, pubKey: HexKey) {
|
||||
const enc = new Nip4WebCryptoEncryptor();
|
||||
const secret = enc.getSharedSecret(privKey, pubKey);
|
||||
return await enc.encryptData(content, secret);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ export class EventPublisher {
|
||||
unwrap(window.nostr?.nip04?.encrypt).call(window.nostr?.nip04, key, content)
|
||||
);
|
||||
} else if (this.#privateKey) {
|
||||
return await EventExt.encryptData(content, key, this.#privateKey);
|
||||
return await EventExt.encryptDm(content, this.#privateKey, key);
|
||||
} else {
|
||||
throw new Error("Can't encrypt content, no private keys available");
|
||||
}
|
||||
|
52
packages/system/src/impl/nip4.ts
Normal file
52
packages/system/src/impl/nip4.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { MessageEncryptor } from "index";
|
||||
|
||||
import { base64 } from "@scure/base";
|
||||
import { secp256k1 } from "@noble/curves/secp256k1";
|
||||
|
||||
export class Nip4WebCryptoEncryptor implements MessageEncryptor {
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const sharedPoint = secp256k1.getSharedSecret(privateKey, "02" + publicKey);
|
||||
const sharedX = sharedPoint.slice(1, 33);
|
||||
return sharedX;
|
||||
}
|
||||
|
||||
async encryptData(content: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const data = new TextEncoder().encode(content);
|
||||
const result = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
const uData = new Uint8Array(result);
|
||||
return `${base64.encode(uData)}?iv=${base64.encode(iv)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the content of the message
|
||||
*/
|
||||
async decryptData(cyphertext: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const cSplit = cyphertext.split("?iv=");
|
||||
const data = base64.decode(cSplit[0]);
|
||||
const iv = base64.decode(cSplit[1]);
|
||||
|
||||
const result = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
return new TextDecoder().decode(result);
|
||||
}
|
||||
|
||||
async #importKey(sharedSecet: Uint8Array) {
|
||||
return await window.crypto.subtle.importKey("raw", sharedSecet, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
|
||||
}
|
||||
}
|
40
packages/system/src/impl/nip44.ts
Normal file
40
packages/system/src/impl/nip44.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { MessageEncryptor } from "index";
|
||||
|
||||
import { base64 } from "@scure/base";
|
||||
import { randomBytes } from '@noble/hashes/utils'
|
||||
import { streamXOR as xchacha20 } from '@stablelib/xchacha20'
|
||||
import { secp256k1 } from "@noble/curves/secp256k1";
|
||||
import { sha256 } from '@noble/hashes/sha256'
|
||||
|
||||
export enum Nip44Version {
|
||||
Reserved = 0x00,
|
||||
XChaCha20 = 0x01
|
||||
}
|
||||
|
||||
export class Nip44Encryptor implements MessageEncryptor {
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const key = secp256k1.getSharedSecret(privateKey, '02' + publicKey)
|
||||
return sha256(key.slice(1, 33));
|
||||
}
|
||||
|
||||
encryptData(content: string, sharedSecret: Uint8Array) {
|
||||
const nonce = randomBytes(24)
|
||||
const plaintext = new TextEncoder().encode(content)
|
||||
const ciphertext = xchacha20(sharedSecret, nonce, plaintext, plaintext);
|
||||
const ctb64 = base64.encode(Uint8Array.from(ciphertext))
|
||||
const nonceb64 = base64.encode(nonce)
|
||||
return JSON.stringify({ ciphertext: ctb64, nonce: nonceb64, v: Nip44Version.XChaCha20 })
|
||||
}
|
||||
|
||||
decryptData(cyphertext: string, sharedSecret: Uint8Array) {
|
||||
const dt = JSON.parse(cyphertext)
|
||||
if (dt.v !== 1) throw new Error('NIP44: unknown encryption version')
|
||||
|
||||
const ciphertext = base64.decode(dt.ciphertext)
|
||||
const nonce = base64.decode(dt.nonce)
|
||||
const plaintext = xchacha20(sharedSecret, nonce, ciphertext, ciphertext)
|
||||
const text = new TextDecoder().decode(plaintext)
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,8 @@ export * from "./EventBuilder";
|
||||
export * from "./NostrLink";
|
||||
export * from "./cache";
|
||||
export * from "./ProfileCache";
|
||||
export * from "./impl/nip4";
|
||||
export * from "./impl/nip44";
|
||||
|
||||
export interface SystemInterface {
|
||||
/**
|
||||
@ -41,3 +43,9 @@ export interface SystemSnapshot {
|
||||
subFilters: Array<ReqFilter>;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface MessageEncryptor {
|
||||
getSharedSecret(privateKey: string, publicKey: string): Promise<Uint8Array> | Uint8Array
|
||||
encryptData(plaintext: string, sharedSecet: Uint8Array): Promise<string> | string
|
||||
decryptData(cyphertext: string, sharedSecet: Uint8Array): Promise<string> | string
|
||||
}
|
45
packages/system/tests/Impl.test.ts
Normal file
45
packages/system/tests/Impl.test.ts
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
import { schnorr, secp256k1 } from "@noble/curves/secp256k1";
|
||||
import { Nip4WebCryptoEncryptor } from "../src/impl/nip4";
|
||||
import { Nip44Encryptor } from "../src/impl/nip44";
|
||||
import { bytesToHex } from "@noble/curves/abstract/utils";
|
||||
|
||||
const aKey = secp256k1.utils.randomPrivateKey();
|
||||
const aPubKey = schnorr.getPublicKey(aKey);
|
||||
const bKey = secp256k1.utils.randomPrivateKey();
|
||||
const bPubKey = schnorr.getPublicKey(bKey);
|
||||
|
||||
describe("NIP-04", () => {
|
||||
it("should encrypt/decrypt", async () => {
|
||||
const msg = "test hello, 123";
|
||||
const enc = new Nip4WebCryptoEncryptor();
|
||||
const sec = enc.getSharedSecret(bytesToHex(aKey), bytesToHex(bPubKey));
|
||||
|
||||
const ciphertext = await enc.encryptData(msg, sec);
|
||||
expect(ciphertext).toMatch(/^.*\?iv=.*$/i);
|
||||
|
||||
const dec = new Nip4WebCryptoEncryptor();
|
||||
const sec2 = enc.getSharedSecret(bytesToHex(bKey), bytesToHex(aPubKey));
|
||||
const plaintext = await dec.decryptData(ciphertext, sec2);
|
||||
expect(plaintext).toEqual(msg);
|
||||
})
|
||||
})
|
||||
|
||||
describe("NIP-44", () => {
|
||||
it("should encrypt/decrypt", () => {
|
||||
const msg = "test hello, 123";
|
||||
const enc = new Nip44Encryptor();
|
||||
const sec = enc.getSharedSecret(bytesToHex(aKey), bytesToHex(bPubKey));
|
||||
|
||||
const ciphertext = enc.encryptData(msg, sec);
|
||||
const jObj = JSON.parse(ciphertext);
|
||||
expect(jObj).toHaveProperty("ciphertext")
|
||||
expect(jObj).toHaveProperty("nonce")
|
||||
expect(jObj.v).toBe(1);
|
||||
|
||||
const dec = new Nip44Encryptor();
|
||||
const sec2 = enc.getSharedSecret(bytesToHex(bKey), bytesToHex(aPubKey));
|
||||
const plaintext = dec.decryptData(ciphertext, sec2);
|
||||
expect(plaintext).toEqual(msg);
|
||||
})
|
||||
})
|
@ -1,3 +1,5 @@
|
||||
import { TextEncoder, TextDecoder } from "util";
|
||||
import { Crypto } from "@peculiar/webcrypto";
|
||||
|
||||
Object.assign(global, { TextDecoder, TextEncoder });
|
||||
Object.assign(globalThis.window.crypto, new Crypto());
|
102
yarn.lock
102
yarn.lock
@ -2059,6 +2059,33 @@
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^12.11.0"
|
||||
|
||||
"@peculiar/asn1-schema@^2.3.6":
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz#3dd3c2ade7f702a9a94dfb395c192f5fa5d6b922"
|
||||
integrity sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==
|
||||
dependencies:
|
||||
asn1js "^3.0.5"
|
||||
pvtsutils "^1.3.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@peculiar/json-schema@^1.1.12":
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339"
|
||||
integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@peculiar/webcrypto@^1.4.3":
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz#078b3e8f598e847b78683dc3ba65feb5029b93a7"
|
||||
integrity sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==
|
||||
dependencies:
|
||||
"@peculiar/asn1-schema" "^2.3.6"
|
||||
"@peculiar/json-schema" "^1.1.12"
|
||||
pvtsutils "^1.3.2"
|
||||
tslib "^2.5.0"
|
||||
webcrypto-core "^1.7.7"
|
||||
|
||||
"@polka/url@^1.0.0-next.20":
|
||||
version "1.0.0-next.21"
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||
@ -2121,9 +2148,9 @@
|
||||
estree-walker "^1.0.1"
|
||||
picomatch "^2.2.2"
|
||||
|
||||
"@scure/base@~1.1.0":
|
||||
"@scure/base@^1.1.1", "@scure/base@~1.1.0":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
|
||||
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
|
||||
|
||||
"@scure/bip32@^1.3.0":
|
||||
@ -2162,6 +2189,40 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^3.0.0"
|
||||
|
||||
"@stablelib/binary@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f"
|
||||
integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==
|
||||
dependencies:
|
||||
"@stablelib/int" "^1.0.1"
|
||||
|
||||
"@stablelib/chacha@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/chacha/-/chacha-1.0.1.tgz#deccfac95083e30600c3f92803a3a1a4fa761371"
|
||||
integrity sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==
|
||||
dependencies:
|
||||
"@stablelib/binary" "^1.0.1"
|
||||
"@stablelib/wipe" "^1.0.1"
|
||||
|
||||
"@stablelib/int@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008"
|
||||
integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==
|
||||
|
||||
"@stablelib/wipe@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36"
|
||||
integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==
|
||||
|
||||
"@stablelib/xchacha20@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/xchacha20/-/xchacha20-1.0.1.tgz#e98808d1f7d8b20e3ff37c71a3062a2a955d9a8c"
|
||||
integrity sha512-1YkiZnFF4veUwBVhDnDYwo6EHeKzQK4FnLiO7ezCl/zu64uG0bCCAUROJaBkaLH+5BEsO3W7BTXTguMbSLlWSw==
|
||||
dependencies:
|
||||
"@stablelib/binary" "^1.0.1"
|
||||
"@stablelib/chacha" "^1.0.1"
|
||||
"@stablelib/wipe" "^1.0.1"
|
||||
|
||||
"@surma/rollup-plugin-off-main-thread@^2.2.3":
|
||||
version "2.2.3"
|
||||
resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz"
|
||||
@ -3393,6 +3454,15 @@ asap@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
|
||||
integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
|
||||
|
||||
asn1js@^3.0.1, asn1js@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38"
|
||||
integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==
|
||||
dependencies:
|
||||
pvtsutils "^1.3.2"
|
||||
pvutils "^1.1.3"
|
||||
tslib "^2.4.0"
|
||||
|
||||
assertion-error@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz"
|
||||
@ -8488,6 +8558,18 @@ pure-rand@^6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306"
|
||||
integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==
|
||||
|
||||
pvtsutils@^1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.2.tgz#9f8570d132cdd3c27ab7d51a2799239bf8d8d5de"
|
||||
integrity sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
pvutils@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
|
||||
integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==
|
||||
|
||||
qr-code-styling@^1.6.0-rc.1:
|
||||
version "1.6.0-rc.1"
|
||||
resolved "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.6.0-rc.1.tgz"
|
||||
@ -9888,6 +9970,11 @@ tslib@^1.8.1:
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.0, tslib@^2.5.0:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913"
|
||||
integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
|
||||
@ -10251,6 +10338,17 @@ wcwidth@^1.0.1:
|
||||
dependencies:
|
||||
defaults "^1.0.3"
|
||||
|
||||
webcrypto-core@^1.7.7:
|
||||
version "1.7.7"
|
||||
resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.7.tgz#06f24b3498463e570fed64d7cab149e5437b162c"
|
||||
integrity sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==
|
||||
dependencies:
|
||||
"@peculiar/asn1-schema" "^2.3.6"
|
||||
"@peculiar/json-schema" "^1.1.12"
|
||||
asn1js "^3.0.1"
|
||||
pvtsutils "^1.3.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz"
|
||||
|
Loading…
x
Reference in New Issue
Block a user