forked from TheAlgorithms/JavaScript
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAffineCipher.js
More file actions
Latest commit
105 lines (94 loc) · 2.83 KB
/
Copy pathAffineCipher.js
File metadata and controls
105 lines (94 loc) · 2.83 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
/**
* @description - The affine cipher is a type of monoalphabetic substitution cipher, where each letter in an alphabet is mapped to its numeric equivalent, encrypted using a simple mathematical function, and converted back to a letter
* @see - [wiki](https://en.wikipedia.org/wiki/Affine_cipher)
*/
import{CoPrimeCheck}from'../Maths/CoPrimeCheck'
// Default key for Affine Cipher
constkey='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
/**
* Fix result for negative value in modulas equation
* @param {Number} n - Constant number
* @param {Number} m - Modulos value
* @return {Number} Return n mod m
*/
functionmod(n,m){
return((n%m)+m)%m
}
/**
* Modular multiplicative inverse
* @param {Number} a - A coefficient
* @param {Number} m - Modulos value
* @return {Number} Return modular multiplicative inverse of coefficient a and modulos m
*/
functioninverseMod(a,m){
for(letx=1;x<m;x++){
if(mod(a*x,m)===1)returnx
}
}
/**
* Argument validation
* @param {String} str - String to be checked
* @param {Number} a - A coefficient to be checked
* @param {Number} b - B coefficient to be checked
* @return {Boolean} Result of the checking
*/
functionisCorrectFormat(str,a,b){
if(typeofa!=='number'||typeofb!=='number'){
thrownewTypeError('Coefficient a, b should be number')
}
if(typeofstr!=='string'){
thrownewTypeError('Argument str should be String')
}
if(!CoPrimeCheck(a,26)){
thrownewError(a+' is not coprime of 26')
}
returntrue
}
/**
* Find character index based on ASCII order
* @param {String} char - Character index to be found
* @return {Boolean} Character index
*/
functionfindCharIndex(char){
returnchar.toUpperCase().charCodeAt(0)-'A'.charCodeAt(0)
}
/**
* Encrypt a Affine Cipher
* @param {String} str - String to be encrypted
* @param {Number} a - A coefficient
* @param {Number} b - B coefficient
* @return {String} result - Encrypted string
*/
functionencrypt(str,a,b){
letresult=''
if(isCorrectFormat(str,a,b)){
for(letx=0;x<str.length;x++){
constcharIndex=findCharIndex(str[x])
if(charIndex<0)result+='-1'+' '
elseresult+=key.charAt(mod(a*charIndex+b,26))+' '
}
}
returnresult.trim()
}
/**
* Decrypt a Affine Cipher
* @param {String} str - String to be decrypted
* @param {Number} a - A coefficient
* @param {Number} b - B coefficient
* @return {String} result - Decrypted string
*/
functiondecrypt(str,a,b){
letresult=''
if(isCorrectFormat(str,a,b)){
str=str.split(' ')
for(letx=0;x<str.length;x++){
if(str[x]==='-1')result+=' '
else{
constcharIndex=findCharIndex(str[x])
result+=key[mod(inverseMod(a,26)*(charIndex-b),26)]
}
}
returnresult
}
}
export{encrypt,decrypt}