Affine is a monoalphabetic substitution cipher. Each letter in the alphabet is mapped to a number, then encrypted/decrypted using a math formula, and finally converted back to a letter.
✅ Perfect Decoding
✅ Uppercase letters (A-Z)
✅ Lowercase letters (a-z)
❌ Numbers (0-9)
❌ Symbols (!@#$)
❌ Emojis (😍🤬👩🏾💻)
Numbers, Symbols, and Emojis
Numbers, symbols, and emoji are outputted as-is by this cipher.
What is “Perfect Decoding”?
Perfect Decoding is when the decoded text exactly matches the text that was encoded.
((coprime * letterPosition) + shift) mod 26
(modInverseOfCoprime * (letterPosition - shift)) mod 26
Based on the current settings for Affine:
coprime = 3shift = 6modInverseOfCoprime = 9((3 * letterPosition) + 6) mod 26
(9 * (letterPosition - 6)) mod 26
Hello World!
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789
!@#$
✨🦄✨
Bsnnw Uwfnp!
GJMPSVYBEHKNQTWZCFILORUXAD
gjmpsvybehknqtwzcfiloruxad
0123456789
!@#$
✨🦄✨
Hello World!
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789
!@#$
✨🦄✨
letterPosition is the index of the lettercoprime and shift are two variables you pick!modInverseOfCoprime is the modular multiplicative inverse of coprimeYou’ll see a lot of references to 26, it’s not a magic number, just the
number of letters in the English alphabet.
letterPositionIndex of the letter in the English alphabet (0-indexed). For example,
A=0, B=1, C=2, and so on until Z=25.
coprimeMust be a number where the only positive integer that divides it and 26 is 1. With that limitation the only valid values are: 1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25
shiftAny integer, positive or negative
modInverseOfCoprimeThe modular multiplicative inverse of the coprime. To be honest, I don’t fully understand the formula.
But, after extensive searching, I got a rough understanding that we need to find a number where the formula below would be correct.
(coprime * x) % 26 = 1
The value of x is the modular multiplicative inverse of coprime. The following javascript function, stolen converted from the examples here calculates the value for x.
function _modInverse (coprime) {
let mod = utils.TOTAL_ALPHA
let inverse = 1
let y = 0
while (coprime > 1) {
let origMod = mod
let origY = y
let quotient = Math.floor(coprime / mod)
mod = coprime % mod
coprime = origMod
y = inverse - quotient * y
inverse = origY
if (inverse < 0) {
inverse += utils.TOTAL_ALPHA
}
}
return inverse
}
mod 26Both formulas for encoding and decoding have mod 26 which performs the modulo (%) operation on the output.
This is a safe-keeping action to guarantee the character is one of the 26 letters in the alphabet. Javascript doesn’t have proper support for mod so this formula is used:
export function mod (a, b) {
return ((a % b) + b) % b
}