3
$\begingroup$

I am trying to create functions for encoding and decoding an affine cipher in Mathematica. I have written these two functions:

EncryptChar[char_, a_, b_] := 
  Module[{alphabet, position, shift, mod},
    alphabet = Alphabet[];
    position = Position[alphabet, char][[1]];
    position = position[[1]];
    shift = Mod[a*position + b, 26];
    Return[alphabet[[shift]]];];

DecryptChar[char_, a_, b_] := 
  Module[{alphabet, position, shift, mod},
    alphabet = Alphabet[];
    position = Position[alphabet, char][[1]];
    position = position[[1]];
    shift = Mod[a^-1*(position - b), 26];
    Return [alphabet[[shift]]];];

And when I try to decode char "p", I get this error:

DecryptChar["p", 3, 5]

During evaluation of In[116]:= Part::pkspec1: The expression 11/3 cannot be used as a part specification. >>

{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}[[11/3]]

What have I done wrong?

$\endgroup$
3
  • 4
    $\begingroup$ Isn't the problem that a^-1 is supposed to be the modular inverse of a rather than just 1/a? Yes: replace a^-1 with PowerMod[a, -1, 26] in the definition of DecryptChar. $\endgroup$
    – march
    Jan 27, 2016 at 0:24
  • $\begingroup$ @march Woops. Just saw this after I posted. +1 $\endgroup$
    – Edmund
    Jan 27, 2016 at 2:00
  • $\begingroup$ In addition to the modulus inverse problem identified by others, shouldn't you check that a is relatively prime to the number of characters in your allowable alphabet (26 in this case)? $\endgroup$ Jan 27, 2016 at 14:57

2 Answers 2

6
$\begingroup$

You are using the wrong inverse in DecryptChar. You should be using the modular multiplicative inverse but you are using the multiplicative inverse.

DecryptChar[char_, a_, b_] :=
 Module[{alphabet, position, shift, mod},
  alphabet = Alphabet[];
  position = First@Flatten@Position[alphabet, char];
  shift = Mod[PowerMod[a, -1, 26] (position - b), 26];
  alphabet[[shift]]
  ]

DecryptChar["p", 3, 5]

(* "u" *)

Hope this helps.

$\endgroup$
2
  • $\begingroup$ @m_goldberg Ah, okay. I just zeroed in on the inverse issue. Thanks. $\endgroup$
    – Edmund
    Jan 27, 2016 at 3:22
  • $\begingroup$ DecryptChar["p", 3, 5] should not give "u" but "m". The OP's algorithm is incorrect. The correct pairings are u <--> n" and "m <--> p $\endgroup$
    – m_goldberg
    Jan 27, 2016 at 3:24
4
$\begingroup$

Edit

(Corrected error in algorithm)

You can reverse the encryption with Solve, which can handle modular equations.

With[{alphabet = Alphabet[]},
  With[{n = Length[alphabet]},
    EncryptChar[char_, a_, b_] :=
      Module[{position, shift},
        position = Position[alphabet, char][[1, 1]] - 1;
        shift = Mod[a position + b, n];
        alphabet[[shift + 1]]];
    DecryptChar[char_, a_, b_] :=
      Module[{position, shift},
        position = Position[alphabet, char][[1, 1]] - 1;
        shift = Solve[a x + b == position, x, Modulus -> n][[1, 1, 2]];
        alphabet[[shift + 1]]]]]

Confirm that the code now works:

(DecryptChar[EncryptChar[#, 3, 5], 3, 5] & /@ Alphabet[]) == Alphabet[]

True

Note: I also cleaned up your code a bit.

Update

I thought about this some more and decided that the problem would be better solved with associations (hash tables). An advantage of this approach is that the coder doesn't to worry about the indexing issues that trouble the OP's code. It is also is concise and efficient.

With[{chars = Alphabet[]},
  With[{n = Length[chars]},
    With[{
        fwdHash = AssociationThread[chars, Range[0, n - 1]],
        bkwHash = AssociationThread[Range[0, n - 1], chars]},
      encryptChar[char_, a_, b_] := bkwHash @ Mod[a fwdHash[char] + b, n];
      decryptChar[char_, a_, b_] :=
        bkwHash @ Solve[a x + b == fwdHash[char], x, Modulus -> n][[1, 1, 2]]]]]

(decryptChar[encryptChar[#, 3, 5], 3, 5] & /@ Alphabet[]) == Alphabet[]

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.