1
+ // The code of an 'A' character (equals to 65).
2
+ const alphabetCodeShift = 'A' . codePointAt ( 0 ) ;
3
+ const englishAlphabetSize = 26 ;
1
4
2
5
/**
3
- * generate key matrix from given keyString
6
+ * Generates key matrix from given keyString.
4
7
*
5
- * @param {integer } length
6
- * @param {string } keyString
7
- * @return {Array[][] } keyMatrix
8
+ * @param {string } keyString - a string to build a key matrix (must be of matrixSize^2 length).
9
+ * @return {number[][] } keyMatrix
8
10
*/
9
- const generateKeyMatrix = ( length , keyString ) => {
11
+ const generateKeyMatrix = ( keyString ) => {
12
+ const matrixSize = Math . sqrt ( keyString . length ) ;
13
+ if ( ! Number . isInteger ( matrixSize ) ) {
14
+ throw new Error (
15
+ 'Invalid key string length. The square root of the key string must be an integer' ,
16
+ ) ;
17
+ }
10
18
const keyMatrix = [ ] ;
11
19
let keyStringIndex = 0 ;
12
- for ( let i = 0 ; i < length ; i += 1 ) {
20
+ for ( let i = 0 ; i < matrixSize ; i += 1 ) {
13
21
const keyMatrixRow = [ ] ;
14
- for ( let j = 0 ; j < length ; j += 1 ) {
15
- keyMatrixRow . push ( ( keyString . codePointAt ( keyStringIndex ) ) % 65 ) ;
22
+ for ( let j = 0 ; j < matrixSize ; j += 1 ) {
23
+ // A → 0, B → 1, ..., a → 32, b → 33, ...
24
+ const charCodeShifted = ( keyString . codePointAt ( keyStringIndex ) ) % alphabetCodeShift ;
25
+ keyMatrixRow . push ( charCodeShifted ) ;
16
26
keyStringIndex += 1 ;
17
27
}
18
28
keyMatrix . push ( keyMatrixRow ) ;
@@ -21,48 +31,54 @@ const generateKeyMatrix = (length, keyString) => {
21
31
} ;
22
32
23
33
/**
24
- * generate message vector from given message
34
+ * Generates a message vector from a given message.
25
35
*
26
- * @param {* } message
27
- * @return {Array } messageVector
36
+ * @param {string } message - the message to encrypt.
37
+ * @return {number[] } messageVector
28
38
*/
29
39
const generateMessageVector = ( message ) => {
30
40
const messageVector = [ ] ;
31
41
for ( let i = 0 ; i < message . length ; i += 1 ) {
32
- messageVector . push ( message . codePointAt ( i ) % 65 ) ;
42
+ messageVector . push ( message . codePointAt ( i ) % alphabetCodeShift ) ;
33
43
}
34
44
return messageVector ;
35
45
} ;
36
46
37
47
/**
38
- * validate data and encrypt message from given message and keyString
48
+ * Encrypts the given message using Hill Cipher.
39
49
*
40
50
* @param {string } message plaintext
41
51
* @param {string } keyString
42
52
* @return {string } cipherString
43
- *
44
53
*/
54
+ export function hillCipherEncrypt ( message , keyString ) {
55
+ // The keyString and message can only contain letters.
56
+ const onlyLettersRegExp = / ^ [ a - z A - Z ] + $ / ;
57
+ if ( ! onlyLettersRegExp . test ( message ) || ! onlyLettersRegExp . test ( keyString ) ) {
58
+ throw new Error ( 'The message and key string can only contain letters' ) ;
59
+ }
60
+
61
+ const keyMatrix = generateKeyMatrix ( keyString ) ;
45
62
46
- export default function hillCipherEncrypt ( message , keyString ) {
47
- const length = keyString . length ** ( 0.5 ) ;
48
63
// keyString.length must equal to square of message.length
49
- if ( ! Number . isInteger ( length ) && length !== message . length ) {
50
- throw new Error ( 'invalid key string length' ) ;
51
- }
52
- // keyString and messange can only contain letters
53
- if ( ! ( / ^ [ a - z A - Z ] + $ / . test ( message ) ) || ! ( / ^ [ A - Z a - z ] + $ / . test ( keyString ) ) ) {
54
- throw new Error ( 'messange and key string can only contain letters' ) ;
64
+ if ( keyMatrix . length !== message . length ) {
65
+ throw new Error ( 'Invalid key string length. The key length must be a square of message length' ) ;
55
66
}
56
67
57
- const keyMatrix = generateKeyMatrix ( length , keyString ) ;
58
68
const messageVector = generateMessageVector ( message ) ;
59
- let ciperString = '' ;
60
- for ( let row = 0 ; row < length ; row += 1 ) {
69
+ let cipherString = '' ;
70
+ for ( let row = 0 ; row < keyMatrix . length ; row += 1 ) {
61
71
let item = 0 ;
62
- for ( let column = 0 ; column < length ; column += 1 ) {
72
+ for ( let column = 0 ; column < keyMatrix . length ; column += 1 ) {
63
73
item += keyMatrix [ row ] [ column ] * messageVector [ column ] ;
64
74
}
65
- ciperString += String . fromCharCode ( ( item % 26 ) + 65 ) ;
75
+ cipherString += String . fromCharCode ( ( item % englishAlphabetSize ) + alphabetCodeShift ) ;
66
76
}
67
- return ciperString ;
77
+
78
+ return cipherString ;
68
79
}
80
+
81
+ // @TODO : Implement this method.
82
+ export const hillCipherDecrypt = ( ) => {
83
+ throw new Error ( 'This method is not implemented yet' ) ;
84
+ } ;
0 commit comments