-
Notifications
You must be signed in to change notification settings - Fork 134
/
hillCipher.js
86 lines (77 loc) · 3.07 KB
/
hillCipher.js
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
import * as mtrx from '../../math/matrix/Matrix';
// Mã của ký tự A (bằng 65).
const alphabetCodeShift = 'A'.codePointAt(0);
const englishAlphabetSize = 26;
/**
* Tạo ma trận khoá từ chuỗi khoá đã cho.
*
* @param {string} keyString - chuỗi khoá để xây dựng ma trận khoá(phải có độ dài là matrixSize^2).
* @return {number[][]} Ma trận khoá
*/
const generateKeyMatrix = (keyString) => {
const matrixSize = Math.sqrt(keyString.length);
if (!Number.isInteger(matrixSize)) {
throw new Error(
'Invalid key string length. The square root of the key string must be an integer',
);
}
let keyStringIndex = 0;
return mtrx.generate(
[matrixSize, matrixSize],
// Callback để nhận giá trị của mỗi ô ma trận .
// Thứ tự mà ma trận đang được điền là từ trái sang phải, từ trên xuống dưới.
() => {
// A → 0, B → 1, ..., a → 32, b → 33, ...
const charCodeShifted = (keyString.codePointAt(keyStringIndex)) % alphabetCodeShift;
keyStringIndex += 1;
return charCodeShifted;
},
);
};
/**
* Tạo vectơ thông điệp từ một thông điệp nhất định.
*
* @param {string} message - thông điệp cần mã hoá.
* @return {number[][]} vector thông điệp.
*/
const generateMessageVector = (message) => {
return mtrx.generate(
[message.length, 1],
// Callback để nhận giá trị của mỗi ô ma trận .
// Thứ tự mà ma trận đang được điền là từ trái sang phải, từ trên xuống dưới.
(cellIndices) => {
const rowIndex = cellIndices[0];
return message.codePointAt(rowIndex) % alphabetCodeShift;
},
);
};
/**
* Mã hoá thông điệp bằng mật mã Hill.
*
* @param {string} message thông điệp dạng văn bản
* @param {string} keyString
* @return {string} chuỗi đã mã hoá
*/
export function hillCipherEncrypt(message, keyString) {
// Khoá và thông điệp chỉ được chứa chữ cái.
const onlyLettersRegExp = /^[a-zA-Z]+$/;
if (!onlyLettersRegExp.test(message) || !onlyLettersRegExp.test(keyString)) {
throw new Error('The message and key string can only contain letters');
}
const keyMatrix = generateKeyMatrix(keyString);
const messageVector = generateMessageVector(message);
// Độ dài khoá phải bằng độ dài thông điệp.
if (keyMatrix.length !== message.length) {
throw new Error('Invalid key string length. The key length must be a square of message length');
}
const cipherVector = mtrx.dot(keyMatrix, messageVector);
let cipherString = '';
for (let row = 0; row < cipherVector.length; row += 1) {
const item = cipherVector[row];
cipherString += String.fromCharCode((item % englishAlphabetSize) + alphabetCodeShift);
}
return cipherString;
}
export const hillCipherDecrypt = () => {
throw new Error('This method is not implemented yet');
};