mirror of
https://github.com/rustfs/console.git
synced 2026-09-19 01:47:44 +08:00
fix: crypto in non-secure contexts
This commit is contained in:
Vendored
-12
@@ -9,8 +9,6 @@ declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
NA: typeof import('naive-ui')['NA']
|
||||
NAlert: typeof import('naive-ui')['NAlert']
|
||||
NAnchor: typeof import('naive-ui')['NAnchor']
|
||||
NAnchorLink: typeof import('naive-ui')['NAnchorLink']
|
||||
NAvatar: typeof import('naive-ui')['NAvatar']
|
||||
NBadge: typeof import('naive-ui')['NBadge']
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
@@ -26,11 +24,9 @@ declare module 'vue' {
|
||||
NDescriptions: typeof import('naive-ui')['NDescriptions']
|
||||
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
|
||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
NDivider: typeof import('naive-ui')['NDivider']
|
||||
NDrawer: typeof import('naive-ui')['NDrawer']
|
||||
NDrawerContent: typeof import('naive-ui')['NDrawerContent']
|
||||
NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
NDynamicTags: typeof import('naive-ui')['NDynamicTags']
|
||||
NEmpty: typeof import('naive-ui')['NEmpty']
|
||||
NFlex: typeof import('naive-ui')['NFlex']
|
||||
NForm: typeof import('naive-ui')['NForm']
|
||||
@@ -38,17 +34,12 @@ declare module 'vue' {
|
||||
NFormItemGi: typeof import('naive-ui')['NFormItemGi']
|
||||
NFormItemGridItem: typeof import('naive-ui')['NFormItemGridItem']
|
||||
NGrid: typeof import('naive-ui')['NGrid']
|
||||
NH1: typeof import('naive-ui')['NH1']
|
||||
NH2: typeof import('naive-ui')['NH2']
|
||||
NH3: typeof import('naive-ui')['NH3']
|
||||
NH4: typeof import('naive-ui')['NH4']
|
||||
NHr: typeof import('naive-ui')['NHr']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
|
||||
NLayout: typeof import('naive-ui')['NLayout']
|
||||
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
|
||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||
NLi: typeof import('naive-ui')['NLi']
|
||||
NList: typeof import('naive-ui')['NList']
|
||||
@@ -57,12 +48,10 @@ declare module 'vue' {
|
||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
NModal: typeof import('naive-ui')['NModal']
|
||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
NOl: typeof import('naive-ui')['NOl']
|
||||
NP: typeof import('naive-ui')['NP']
|
||||
NPageHeader: typeof import('naive-ui')['NPageHeader']
|
||||
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
|
||||
NProgress: typeof import('naive-ui')['NProgress']
|
||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
NSelect: typeof import('naive-ui')['NSelect']
|
||||
NSpace: typeof import('naive-ui')['NSpace']
|
||||
NSpin: typeof import('naive-ui')['NSpin']
|
||||
@@ -73,7 +62,6 @@ declare module 'vue' {
|
||||
NTag: typeof import('naive-ui')['NTag']
|
||||
NText: typeof import('naive-ui')['NText']
|
||||
NThing: typeof import('naive-ui')['NThing']
|
||||
NUl: typeof import('naive-ui')['NUl']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
|
||||
Generated
+1
@@ -25,6 +25,7 @@
|
||||
"json-editor-vue": "^0.17.3",
|
||||
"lodash": "^4.17.21",
|
||||
"rustfs": "^8.0.2",
|
||||
"node-forge": "^1.3.1",
|
||||
"nuxt": "^3.15.4",
|
||||
"nuxtjs-naive-ui": "^1.0.2",
|
||||
"pinia": "^2.3.0",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"json-editor-vue": "^0.17.3",
|
||||
"lodash": "^4.17.21",
|
||||
"rustfs": "^8.0.2",
|
||||
"node-forge": "^1.3.1",
|
||||
"nuxt": "^3.15.4",
|
||||
"nuxtjs-naive-ui": "^1.0.2",
|
||||
"pinia": "^2.3.0",
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// @ts-nocheck
|
||||
// This plugin imports the SubtleCrypto polyfill for browser compatibility
|
||||
import forge from "node-forge";
|
||||
|
||||
// Polyfill for SubtleCrypto
|
||||
// https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features/
|
||||
// This is only needed for non-secure contexts (http://localhost:3000)
|
||||
// and is used to provide a consistent API for cryptographic operations
|
||||
// across different environments. It uses the forge library to implement
|
||||
// the SubtleCrypto API in a way that is compatible with the Web Crypto API.
|
||||
// The polyfill is loaded dynamically to avoid unnecessary overhead in secure contexts.
|
||||
export default defineNuxtPlugin(() => {
|
||||
if (!globalThis.crypto) {
|
||||
globalThis.crypto = {} as Crypto;
|
||||
}
|
||||
|
||||
const cryptoObj = globalThis.crypto;
|
||||
|
||||
if (!cryptoObj.subtle) {
|
||||
cryptoObj.subtle = {
|
||||
async digest(algorithm: string | Algorithm, data: BufferSource): Promise<ArrayBuffer> {
|
||||
if (algorithm !== "SHA-256" && (algorithm as Algorithm).name !== "SHA-256") {
|
||||
throw new Error("Only SHA-256 is supported.");
|
||||
}
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(forge.util.createBuffer(new Uint8Array(data as ArrayBuffer)).getBytes());
|
||||
return new Uint8Array(md.digest().bytes().split("").map(c => c.charCodeAt(0))).buffer;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.randomUUID) {
|
||||
cryptoObj.randomUUID = function () {
|
||||
const randomBytes = cryptoObj.getRandomValues(new Uint8Array(16));
|
||||
randomBytes[6] = (randomBytes[6] & 0x0f) | 0x40; // UUID version 4
|
||||
randomBytes[8] = (randomBytes[8] & 0x3f) | 0x80; // UUID variant 1
|
||||
return [...randomBytes]
|
||||
.map((b, i) =>
|
||||
[4, 6, 8, 10].includes(i) ? `-${b.toString(16).padStart(2, "0")}` : b.toString(16).padStart(2, "0")
|
||||
)
|
||||
.join("");
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.getRandomValues) {
|
||||
cryptoObj.getRandomValues = function (arr: Uint8Array): Uint8Array {
|
||||
const randomBytes = forge.random.getBytesSync(arr.length);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] = randomBytes.charCodeAt(i);
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.generateKey) {
|
||||
cryptoObj.subtle.generateKey = async function (
|
||||
algorithm: GenerateKeyParams,
|
||||
extractable: boolean,
|
||||
keyUsages: string[]
|
||||
): Promise<CryptoKeyPair> {
|
||||
if (algorithm.name !== "ECDSA" || algorithm.namedCurve !== "P-256") {
|
||||
throw new Error("Only ECDSA with P-256 is supported.");
|
||||
}
|
||||
const keys = forge.pki.ec.generateKeyPair({ namedCurve: "P-256" });
|
||||
return {
|
||||
privateKey: keys.privateKey as CryptoKey,
|
||||
publicKey: keys.publicKey as CryptoKey,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.sign) {
|
||||
cryptoObj.subtle.sign = async function (
|
||||
algorithm: Algorithm,
|
||||
key: CryptoKey,
|
||||
data: BufferSource
|
||||
): Promise<ArrayBuffer> {
|
||||
if (algorithm.name !== "ECDSA" || algorithm.hash.name !== "SHA-256") {
|
||||
throw new Error("Only ECDSA with SHA-256 is supported.");
|
||||
}
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(forge.util.createBuffer(new Uint8Array(data as ArrayBuffer)).getBytes());
|
||||
const signature = forge.pki.ec.sign(md, key);
|
||||
return new Uint8Array(signature.split("").map(c => c.charCodeAt(0))).buffer;
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.verify) {
|
||||
cryptoObj.subtle.verify = async function (
|
||||
algorithm: Algorithm,
|
||||
key: CryptoKey,
|
||||
signature: BufferSource,
|
||||
data: BufferSource
|
||||
): Promise<boolean> {
|
||||
if (algorithm.name !== "ECDSA" || algorithm.hash.name !== "SHA-256") {
|
||||
throw new Error("Only ECDSA with SHA-256 is supported.");
|
||||
}
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(forge.util.createBuffer(new Uint8Array(data as ArrayBuffer)).getBytes());
|
||||
return forge.pki.ec.verify(md, key, signature);
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.exportKey) {
|
||||
cryptoObj.subtle.exportKey = async function (
|
||||
format: string,
|
||||
key: CryptoKey
|
||||
): Promise<JsonWebKey | ArrayBuffer> {
|
||||
if (format === "jwk") {
|
||||
if ((key as any).type === "private") {
|
||||
return forge.pki.privateKeyToJwk(key) as JsonWebKey;
|
||||
} else if ((key as any).type === "public") {
|
||||
return forge.pki.publicKeyToJwk(key) as JsonWebKey;
|
||||
}
|
||||
}
|
||||
throw new Error("Unsupported export key format or type.");
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.importKey) {
|
||||
cryptoObj.subtle.importKey = async function (
|
||||
format: string,
|
||||
keyData: JsonWebKey | ArrayBuffer,
|
||||
algorithm: Algorithm,
|
||||
extractable: boolean,
|
||||
keyUsages: string[]
|
||||
): Promise<CryptoKey> {
|
||||
if (format === "jwk") {
|
||||
if (keyData.type === "private") {
|
||||
return forge.pki.jwkToPrivateKey(keyData) as CryptoKey;
|
||||
} else if (keyData.type === "public") {
|
||||
return forge.pki.jwkToPublicKey(keyData) as CryptoKey;
|
||||
}
|
||||
}
|
||||
throw new Error("Unsupported import key format or type.");
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.encrypt) {
|
||||
cryptoObj.subtle.encrypt = async function (
|
||||
algorithm: Algorithm,
|
||||
key: CryptoKey,
|
||||
data: BufferSource
|
||||
): Promise<ArrayBuffer> {
|
||||
throw new Error("Encrypt not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
if (!cryptoObj.subtle.decrypt) {
|
||||
cryptoObj.subtle.decrypt = async function (
|
||||
algorithm: Algorithm,
|
||||
key: CryptoKey,
|
||||
data: BufferSource
|
||||
): Promise<ArrayBuffer> {
|
||||
throw new Error("Decrypt not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
provide: {
|
||||
crypto: cryptoObj,
|
||||
},
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user