refactor(crypto): 优化加密功能并添加base64工具
- 重命名加密函数以更准确反映用途 - 提取base64转换逻辑到独立工具文件 - 简化文本加密流程,移除冗余代码
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
# DONE 🎉
|
||||
- 图片上传
|
||||
- 图片 paste上传,drop上传
|
||||
- 图片预览,保存
|
||||
- 图片预览,保存 自动下载按钮
|
||||
- 重构文本加解密节点
|
||||
# TODO 🚧
|
||||
- 视频上传,预览,保存解密
|
||||
|
||||
# PLAN 📝
|
||||
- fetch hook,/view fetch encrypted文件时自动转换
|
||||
- service worker 加解密
|
||||
- 设置界面,配置、查看密钥对 exchange密钥对按钮
|
||||
+7
-53
@@ -7,6 +7,8 @@ import type {
|
||||
ComfyApi,
|
||||
ComfyNodeDef,
|
||||
} from "@comfyorg/comfyui-frontend-types";
|
||||
import { encryptDataWithServerKey, encryptFileWithServerKey } from "./utils/cryptoUtils.js";
|
||||
import { bytesToBase64 } from "./utils/base64Utils.js";
|
||||
const app: ComfyApp = rawApp;
|
||||
const api: ComfyApi = rawApi;
|
||||
|
||||
@@ -46,66 +48,21 @@ async function getPublicKey(): Promise<string | null> {
|
||||
|
||||
// 使用公钥加密文本
|
||||
async function encryptText(
|
||||
text: string,
|
||||
publicKey?: string
|
||||
text: string
|
||||
): Promise<string> {
|
||||
publicKey ??= await getPublicKey() ?? undefined;
|
||||
if (!publicKey) {
|
||||
throw new Error(
|
||||
"Failed to get public key for encryption"
|
||||
);
|
||||
}
|
||||
try {
|
||||
// 将PEM格式的公钥转换为CryptoKey对象
|
||||
const pemHeader = "-----BEGIN PUBLIC KEY-----";
|
||||
const pemFooter = "-----END PUBLIC KEY-----";
|
||||
const pemContents = publicKey
|
||||
.substring(
|
||||
publicKey.indexOf(pemHeader) + pemHeader.length,
|
||||
publicKey.indexOf(pemFooter)
|
||||
)
|
||||
.replace(/\s/g, "");
|
||||
|
||||
// 解码Base64
|
||||
const binaryDer = window.atob(pemContents);
|
||||
const binaryDerArray = new Uint8Array(binaryDer.length);
|
||||
for (let i = 0; i < binaryDer.length; i++) {
|
||||
binaryDerArray[i] = binaryDer.charCodeAt(i);
|
||||
}
|
||||
|
||||
// 导入公钥
|
||||
const cryptoKey = await window.crypto.subtle.importKey(
|
||||
"spki",
|
||||
binaryDerArray,
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
hash: "SHA-256",
|
||||
},
|
||||
false,
|
||||
["encrypt"]
|
||||
);
|
||||
|
||||
// 加密文本
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(text);
|
||||
const encrypted = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
},
|
||||
cryptoKey,
|
||||
data
|
||||
const encrypted = await encryptDataWithServerKey(
|
||||
new TextEncoder().encode(text)
|
||||
);
|
||||
|
||||
// 转换为Base64
|
||||
const encryptedBase64 = btoa(
|
||||
String.fromCharCode(...new Uint8Array(encrypted))
|
||||
);
|
||||
const encryptedBase64 = bytesToBase64(encrypted);
|
||||
|
||||
// 添加前缀标识这是加密数据
|
||||
return "ENCRYPTED:" + encryptedBase64;
|
||||
} catch (error) {
|
||||
console.error("Encryption error:", error);
|
||||
return text; // 加密失败时返回原文本
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,9 +95,6 @@ app.registerExtension({
|
||||
|
||||
let prompt = "";
|
||||
|
||||
|
||||
|
||||
|
||||
const encryptedText = await encryptText(
|
||||
textWidget.value
|
||||
);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export function base64ToBytes(base64: string) {
|
||||
return new Uint8Array(atob(base64).split("").map(n => n.charCodeAt(0)))
|
||||
}
|
||||
|
||||
export function bytesToBase64(bytes: Uint8Array): string {
|
||||
return btoa([...bytes].map((n) => String.fromCharCode(n)).join(""));
|
||||
}
|
||||
@@ -71,12 +71,14 @@ async function encryptData(data: Uint8Array, publicKeyPem: string): Promise<Uint
|
||||
* @returns 加密后的数据
|
||||
*/
|
||||
export async function encryptFileWithServerKey(file: File): Promise<Uint8Array> {
|
||||
const serverKeys = await getServerKeysWithExchange();
|
||||
|
||||
// 读取文件内容
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const data = new Uint8Array(arrayBuffer);
|
||||
return await encryptDataWithServerKey(data);
|
||||
}
|
||||
|
||||
export async function encryptDataWithServerKey(data: Uint8Array): Promise<Uint8Array> {
|
||||
const serverKeys = await getServerKeysWithExchange();
|
||||
return await encryptData(data, serverKeys.publicKey);
|
||||
}
|
||||
|
||||
@@ -167,7 +169,7 @@ async function decryptData(encryptedData: Uint8Array, privateKeyPem: string): Pr
|
||||
* @param encryptedData 加密的数据
|
||||
* @returns 解密后的数据
|
||||
*/
|
||||
export async function decryptFileWithServerKey(encryptedData: Uint8Array): Promise<Uint8Array> {
|
||||
export async function decryptDataWithServerKey(encryptedData: Uint8Array): Promise<Uint8Array> {
|
||||
const serverKeys = await getServerKeysWithExchange();
|
||||
return await decryptData(encryptedData, serverKeys.privateKey);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import type { ComfyApi } from "@comfyorg/comfyui-frontend-types";
|
||||
import { decryptFileWithServerKey, decryptFileWithClientKey } from "./cryptoUtils.js";
|
||||
import { decryptDataWithServerKey, decryptFileWithClientKey } from "./cryptoUtils.js";
|
||||
import { getMimeTypeFromFilename } from "./fileUtils.js";
|
||||
|
||||
export interface ImageLoadParams {
|
||||
@@ -33,7 +33,7 @@ export async function loadEncryptedImageFromFilename(filename: string): Promise<
|
||||
const encryptedData = new Uint8Array(encryptedArrayBuffer);
|
||||
|
||||
// 使用服务端私钥解密(UploadImage场景)
|
||||
const decryptedData = await decryptFileWithServerKey(encryptedData);
|
||||
const decryptedData = await decryptDataWithServerKey(encryptedData);
|
||||
|
||||
// 转换为Blob URL
|
||||
const blob = new Blob([new Uint8Array(decryptedData)], {
|
||||
|
||||
Reference in New Issue
Block a user