refactor(crypto): 优化加密功能并添加base64工具

- 重命名加密函数以更准确反映用途
- 提取base64转换逻辑到独立工具文件
- 简化文本加密流程,移除冗余代码
This commit is contained in:
Suzu008
2025-10-12 12:26:43 +08:00
parent 6ed9ea5b1f
commit b809568a75
5 changed files with 34 additions and 58 deletions
+13
View File
@@ -0,0 +1,13 @@
# DONE 🎉
- 图片上传
- 图片 paste上传,drop上传
- 图片预览,保存
- 图片预览,保存 自动下载按钮
- 重构文本加解密节点
# TODO 🚧
- 视频上传,预览,保存解密
# PLAN 📝
- fetch hook,/view fetch encrypted文件时自动转换
- service worker 加解密
- 设置界面,配置、查看密钥对 exchange密钥对按钮
+7 -53
View File
@@ -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
);
+7
View File
@@ -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(""));
}
+5 -3
View File
@@ -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);
}
+2 -2
View File
@@ -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)], {