|
1 |
| -import{createDecipheriv,createHash}from"crypto"; |
| 1 | +import{createDecipheriv,pbkdf2Sync}from"crypto"; |
2 | 2 | import{badRequest}from"../common/error";
|
3 | 3 |
|
4 |
| -// Spring's Encryptors.text uses AES-256-CBC with a key derived from password and salt (hex). |
5 |
| -// The encrypted string format is: hex(salt) + encryptedBase64 |
6 |
| -// See: https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/encrypt/Encryptors.html |
7 |
| - |
| 4 | +// Spring's Encryptors.text uses AES-256-CBC with PBKDF2 (HmacSHA1, 1024 iterations). |
8 | 5 | constALGORITHM="aes-256-cbc";
|
9 | 6 | constKEY_LENGTH=32;// 256 bits
|
10 | 7 | constIV_LENGTH=16;// 128 bits
|
| 8 | +constITERATIONS=1024; |
| 9 | +constDIGEST="sha1"; |
11 | 10 |
|
12 | 11 | // You must set these to match your Java config:
|
13 | 12 | constPASSWORD=process.env.LOWCODER_NODE_SERVICE_SECRET||"lowcoderpwd";
|
14 | 13 | constSALT_HEX=process.env.LOWCODER_NODE_SERVICE_SECRET_SALT||"lowcodersalt";
|
15 | 14 |
|
16 | 15 | /**
|
17 |
| - * Convert a string to its binary representation, then to a hex string. |
18 |
| - */ |
19 |
| -functionstringToHexFromBinary(str:string):string{ |
20 |
| -// Convert string to binary (Buffer), then to hex string |
21 |
| -returnBuffer.from(str,"utf8").toString("hex"); |
22 |
| -} |
23 |
| - |
24 |
| -/** |
25 |
| - * Derive key from password and salt using SHA-256 (Spring's default). |
| 16 | + * Derive key from password and salt using PBKDF2WithHmacSHA1 (Spring's default). |
26 | 17 | */
|
27 | 18 | functionderiveKey(password:string,saltHex:string):Buffer{
|
28 |
| -// Convert salt string to binary, then to hex string |
29 |
| -constsaltHexFromBinary=stringToHexFromBinary(saltHex); |
30 |
| -constsalt=Buffer.from(saltHexFromBinary,"hex"); |
31 |
| -consthash=createHash("sha256"); |
32 |
| -hash.update(password); |
33 |
| -hash.update(salt); |
34 |
| -returnhash.digest(); |
| 19 | +constsalt=Buffer.from(saltHex,"utf8"); |
| 20 | +returnpbkdf2Sync(password,salt,ITERATIONS,KEY_LENGTH,DIGEST); |
35 | 21 | }
|
36 | 22 |
|
37 | 23 | /**
|
38 | 24 | * Decrypt a string encrypted by Spring's Encryptors.text.
|
39 | 25 | */
|
40 | 26 | exportasyncfunctiondecryptString(encrypted:string):Promise<string>{
|
41 | 27 | try{
|
42 |
| -// Spring's format: hex(salt) + encryptedBase64 |
43 |
| -// But if you know salt, encrypted is just Base64(IV + ciphertext) |
| 28 | +// Spring's format: hex(salt) + encryptedHex(IV + ciphertext) |
44 | 29 | constkey=deriveKey(PASSWORD,SALT_HEX);
|
45 | 30 |
|
46 |
| -// Spring's Encryptors.text prepends a random IV (16 bytes) to the ciphertext, all base64 encoded. |
47 |
| -constencryptedBuf=Buffer.from(encrypted,"base64"); |
| 31 | +constencryptedBuf=Buffer.from(encrypted,"hex"); |
48 | 32 | constiv=encryptedBuf.slice(0,IV_LENGTH);
|
49 | 33 | constciphertext=encryptedBuf.slice(IV_LENGTH);
|
50 | 34 |
|
|