summaryrefslogtreecommitdiff
path: root/lib/dolce/crypto-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dolce/crypto-utils.ts')
-rw-r--r--lib/dolce/crypto-utils.ts142
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/dolce/crypto-utils.ts b/lib/dolce/crypto-utils.ts
new file mode 100644
index 00000000..1fb310b2
--- /dev/null
+++ b/lib/dolce/crypto-utils.ts
@@ -0,0 +1,142 @@
+/**
+ * DOLCE 파일 다운로드용 DES 암호화 유틸리티
+ * C# DESCryptoServiceProvider와 호환되는 Node.js 구현
+ *
+ * OpenSSL 3.0 호환 처리:
+ * - Node.js 17+ 환경에서 DES는 레거시 알고리즘으로 분류됨
+ * - 에러 발생 시 crypto-utils-legacy.ts의 수동 구현 사용
+ */
+
+import crypto from "crypto";
+
+// 암호화 키 (8바이트)
+const DES_KEY = Buffer.from("4fkkdijg", "ascii");
+
+// OpenSSL 3.0 환경 감지
+let useModernCrypto = true;
+
+/**
+ * DES ECB 모드로 문자열 암호화
+ * @param plainText 암호화할 평문
+ * @returns Base64 인코딩된 암호문
+ */
+export function encryptDES(plainText: string): string {
+ // 처음 호출 시 OpenSSL 지원 여부 확인
+ if (useModernCrypto) {
+ try {
+ const cipher = crypto.createCipheriv("des-ecb", DES_KEY, Buffer.alloc(0));
+ cipher.setAutoPadding(true);
+
+ let encrypted = cipher.update(plainText, "utf8", "base64");
+ encrypted += cipher.final("base64");
+
+ return encrypted.replace(/\+/g, "|||");
+ } catch (error: any) {
+ // OpenSSL 3.0 에러 감지
+ if (error.message?.includes("unsupported") || error.message?.includes("digital envelope")) {
+ console.warn("[DOLCE] OpenSSL 3.0 감지, 레거시 구현으로 전환합니다.");
+ useModernCrypto = false;
+ // 레거시 구현으로 재시도
+ return encryptDESLegacy(plainText);
+ }
+ throw error;
+ }
+ } else {
+ return encryptDESLegacy(plainText);
+ }
+}
+
+/**
+ * 레거시 DES 암호화 (OpenSSL 3.0 대체)
+ */
+function encryptDESLegacy(plainText: string): string {
+ try {
+ const { encryptDES: legacyEncrypt } = require("./crypto-utils-legacy");
+ return legacyEncrypt(plainText);
+ } catch (error) {
+ console.error("DES 암호화 실패:", error);
+ throw new Error(`암호화 중 오류가 발생했습니다: ${error}`);
+ }
+}
+
+/**
+ * DES ECB 모드로 문자열 복호화
+ * @param encryptedText Base64 인코딩된 암호문
+ * @returns 복호화된 평문
+ */
+export function decryptDES(encryptedText: string): string {
+ if (useModernCrypto) {
+ try {
+ const restored = encryptedText.replace(/\|\|\|/g, "+");
+ const decipher = crypto.createDecipheriv("des-ecb", DES_KEY, Buffer.alloc(0));
+ decipher.setAutoPadding(true);
+
+ let decrypted = decipher.update(restored, "base64", "utf8");
+ decrypted += decipher.final("utf8");
+
+ return decrypted.replace(/\0+$/, "");
+ } catch (error: any) {
+ if (error.message?.includes("unsupported") || error.message?.includes("digital envelope")) {
+ console.warn("[DOLCE] OpenSSL 3.0 감지, 레거시 구현으로 전환합니다.");
+ useModernCrypto = false;
+ return decryptDESLegacy(encryptedText);
+ }
+ throw error;
+ }
+ } else {
+ return decryptDESLegacy(encryptedText);
+ }
+}
+
+/**
+ * 레거시 DES 복호화 (OpenSSL 3.0 대체)
+ */
+function decryptDESLegacy(encryptedText: string): string {
+ try {
+ const { decryptDES: legacyDecrypt } = require("./crypto-utils-legacy");
+ return legacyDecrypt(encryptedText);
+ } catch (error) {
+ console.error("DES 복호화 실패:", error);
+ throw new Error(`복호화 중 오류가 발생했습니다: ${error}`);
+ }
+}
+
+/**
+ * DOLCE 파일 다운로드용 암호화 키 생성
+ * @param fileId 파일 ID
+ * @param userId 사용자 ID
+ * @param fileName 파일명
+ * @returns 암호화된 키
+ */
+export function createDolceDownloadKey(
+ fileId: string,
+ userId: string,
+ fileName: string
+): string {
+ // FileId↔UserId↔FileName 형식으로 조합
+ const plainText = `${fileId}↔${userId}↔${fileName}`;
+
+ // DES 암호화
+ return encryptDES(plainText);
+}
+
+/**
+ * 테스트용: 암호화/복호화 검증
+ */
+export function testDESEncryption(testString: string): {
+ original: string;
+ encrypted: string;
+ decrypted: string;
+ match: boolean;
+} {
+ const encrypted = encryptDES(testString);
+ const decrypted = decryptDES(encrypted);
+
+ return {
+ original: testString,
+ encrypted,
+ decrypted,
+ match: testString === decrypted,
+ };
+}
+