1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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,
};
}
|