Initial commit
This commit is contained in:
92
basics.ts
Normal file
92
basics.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { range, englishFreqs } from './utils';
|
||||
|
||||
type HexToBuff = (hex: string) => Buffer;
|
||||
export const hexToBuff: HexToBuff = (hex) => Buffer.from(hex, 'hex');
|
||||
|
||||
type BuffTo64 = (buff: Buffer) => string;
|
||||
export const buffTo64: BuffTo64 = (buff) => buff.toString('base64');
|
||||
|
||||
type XorBuffers = (buff1: Buffer, buff2: Buffer) => Buffer;
|
||||
export const xorBuffers: XorBuffers = (buff1, buff2) => {
|
||||
const resBuff = Buffer.alloc(buff1.length);
|
||||
range(0, buff1.length).forEach(i => {
|
||||
resBuff[i] = buff1[i] ^ buff2[i];
|
||||
});
|
||||
return resBuff;
|
||||
};
|
||||
|
||||
type EncryptSingleByte = (msg: Buffer, key: number) => Buffer;
|
||||
export const encryptSingleByte: EncryptSingleByte = (msg, key) => {
|
||||
const resBuffer = Buffer.alloc(msg.length);
|
||||
range(0, msg.length).forEach(i => {
|
||||
resBuffer[i] = msg[i] ^ key;
|
||||
});
|
||||
return resBuffer;
|
||||
};
|
||||
|
||||
type DecryptSingleByte = (msg: Buffer, key: number) => Buffer;
|
||||
export const decryptSingleByte: DecryptSingleByte = (msg, key) => {
|
||||
const resBuffer = Buffer.alloc(msg.length);
|
||||
range(0, msg.length).forEach(i => {
|
||||
resBuffer[i] = msg[i] ^ key;
|
||||
});
|
||||
return resBuffer;
|
||||
};
|
||||
|
||||
type EnglishByteFreqs = () => { [id: number]: number };
|
||||
const englishByteFreqs: EnglishByteFreqs = () => {
|
||||
const byteFreqs = {} as { [id: number]: number };
|
||||
range(0, 255).forEach(i => byteFreqs[i] = 0);
|
||||
|
||||
Object.keys(englishFreqs).forEach(k => byteFreqs[k] = englishFreqs[k]);
|
||||
|
||||
return byteFreqs;
|
||||
};
|
||||
|
||||
type ByteFreqs = (buff: Buffer) => { [id: number]: number };
|
||||
const byteFreqs: ByteFreqs = (buff) => {
|
||||
const freqs = {} as { [id: number]: number };
|
||||
let n = 0;
|
||||
range(0, 255).forEach(i => freqs[i] = 0);
|
||||
|
||||
buff.forEach(b => {
|
||||
freqs[b]++;
|
||||
n++;
|
||||
});
|
||||
|
||||
Object.keys(freqs).forEach(b => freqs[b] = freqs[b] / n);
|
||||
|
||||
return freqs;
|
||||
};
|
||||
|
||||
type ScoreBuffer = (buff: Buffer) => number;
|
||||
export const scoreBuffer: ScoreBuffer = (buff) => {
|
||||
const msgLower = Buffer.from(buff.toString('utf-8').toLowerCase(), 'utf-8');
|
||||
const engBFreqs = englishByteFreqs();
|
||||
|
||||
const msgFreq = byteFreqs(msgLower);
|
||||
|
||||
let [cosSimilarity, normMsgFreq, normEngFreq] = [0, 0, 0];
|
||||
|
||||
range(0, 255).forEach(i => {
|
||||
cosSimilarity += msgFreq[i] * engBFreqs[i];
|
||||
normMsgFreq += msgFreq[i] ** 2;
|
||||
normEngFreq += engBFreqs[i] ** 2;
|
||||
});
|
||||
normMsgFreq = Math.sqrt(normMsgFreq);
|
||||
normEngFreq = Math.sqrt(normEngFreq);
|
||||
cosSimilarity /= normMsgFreq * normEngFreq;
|
||||
|
||||
return cosSimilarity;
|
||||
};
|
||||
|
||||
type CrackSingleByteKeyMsg = (msg: string) => string;
|
||||
export const crackSingleByteKeyMsg: CrackSingleByteKeyMsg = (msg) => {
|
||||
const candidates = [] as [number, string][];
|
||||
range(0, 255).forEach(i => {
|
||||
const decrypted = decryptSingleByte(Buffer.from(msg, 'hex'), i);
|
||||
candidates.push([scoreBuffer(decrypted), decrypted.toString('utf-8')]);
|
||||
});
|
||||
candidates.sort((a, b) => b[0] - a[0]);
|
||||
return candidates[0][1];
|
||||
};
|
Reference in New Issue
Block a user