-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencrypt.ts
More file actions
134 lines (117 loc) · 5.52 KB
/
encrypt.ts
File metadata and controls
134 lines (117 loc) · 5.52 KB
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
import * as readline from 'readline';
import * as crypto from 'crypto';
import keysConfig from './keys.json';
import {
encryptSubstitution,
encryptCaesar,
railFenceEncrypt,
addHiddenPadding,
getKeyShifts,
getRepeatingShifts,
encryptMath,
stretchKey,
generateHMAC,
generateRandomSalt,
generateRandomIV,
deriveKeys,
aesEncrypt,
getPipelineOrder
} from './cipher';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function question(query: string): Promise<string> {
return new Promise(resolve => rl.question(query, resolve));
}
async function main() {
try {
const key = await question("Enter a key: ");
const plaintext = await question("Enter the plaintext: ");
let numRoundsStr = await question("Enter the number of rounds for encryption: ");
let numRounds = parseInt(numRoundsStr) || 1;
const liveSalt = generateRandomSalt();
const masterKeyBuffer = stretchKey(key, liveSalt);
const { aesKey, hmacKey } = deriveKeys(masterKeyBuffer, liveSalt);
const masterKeyHex = masterKeyBuffer.toString('hex');
let state = plaintext;
let iv = "";
let tag = "";
let hmac = "";
const masterPipeline = (keysConfig as any).MASTER_PIPELINE;
const legacyKeyShifts = getKeyShifts(key);
const legacyRepeatingShifts = getRepeatingShifts(legacyKeyShifts, numRounds);
// console.log(`\n--- STARTING ENCRYPTION PIPELINE ---`);
// console.log(`Initial Plaintext: "${plaintext}"`);
for (const stage of masterPipeline) {
// console.log(`\n>>> EXECUTING STAGE: ${stage.toUpperCase()}`);
if (stage === "substitution" && (keysConfig as any).ENABLE_SUBSTITUTION_LAYER) {
// state = encryptSubstitution(state);
// console.log(`[Substitution] Result: ${state}`);
} else if (stage === "chaos") {
// console.log(`Entering Chaos Layer (${numRounds} rounds)...`);
for (let round = 0; round < numRounds; round++) {
const legacyRoundShift = legacyRepeatingShifts[round];
const roundDigest = crypto.createHash('sha256').update(masterKeyHex + round.toString() + legacyRoundShift.toString()).digest();
const shift = roundDigest[0];
const modifier = roundDigest[1];
const pipelineOrder = getPipelineOrder(modifier);
// console.log(` [Round ${round + 1}] (Shift: ${shift}, Sequence: ${pipelineOrder.join(' -> ')})`);
for (const step of pipelineOrder) {
let stepName = "";
if (step === "caesar" && (keysConfig as any).ENABLE_CAESAR_LAYER) {
state = encryptCaesar(state, shift);
stepName = "Caesar";
} else if (step === "substitution" && (keysConfig as any).ENABLE_SUBSTITUTION_LAYER) {
state = encryptSubstitution(state);
stepName = "Substitution";
} else if (step === "rail_fence" && (keysConfig as any).ENABLE_RAIL_FENCE_LAYER) {
state = railFenceEncrypt(state);
stepName = "Rail Fence";
} else if (step === "math" && (keysConfig as any).ENABLE_MATH_LAYER) {
state = encryptMath(state, shift);
stepName = "Math (Affine)";
}
// if (stepName) {
// console.log(` - ${stepName.padEnd(15)}: ${state}`);
// }
}
}
} else if (stage === "padding") {
state = addHiddenPadding(state);
// console.log(`[Padding] Result: ${state}`);
} else if (stage === "aes" && (keysConfig as any).AES_ENABLED) {
iv = generateRandomIV();
const aesResult = aesEncrypt(state, aesKey, iv);
state = aesResult.ciphertext;
tag = aesResult.tag;
// console.log(`[AES-256-GCM] Ciphertext: ${state}`);
// console.log(`[AES-256-GCM] Auth Tag: ${tag}`);
} else if (stage === "hmac" && (keysConfig as any).ENABLE_HMAC) {
const hmacPayload = state + liveSalt + iv + tag;
hmac = generateHMAC(hmacKey, hmacPayload);
// console.log(`[HMAC-SHA384] Signature: ${hmac}`);
}
}
// --- FINAL DETERMINISTIC NORMALIZATION ---
// If the final stage was not AES, the payload is still a string.
// We must Base64 encode it once for safe transport in the JSON.
const lastStage = masterPipeline[masterPipeline.length - 1];
const finalData = (lastStage === "aes" && (keysConfig as any).AES_ENABLED) ? state : Buffer.from(state, 'utf16le').toString('base64');
const payloadObj = {
data: finalData,
hmac,
salt: liveSalt,
iv,
tag
};
const jsonStr = JSON.stringify(payloadObj);
const transportSafePayload = Buffer.from(jsonStr, 'utf-8').toString('base64');
console.log(`\nFinal secure JSON payload (Base64 wrapper): \n${transportSafePayload}\n`);
} catch (err) {
console.error(err);
} finally {
rl.close();
}
}
main();