Updated answer
This is Enigma.
Notice that Enigma is symmetric. Thus you can encode and decode at the same place. In the following example, the first input AN ENIGMA MACHINE...
comes from the Wikipedia article. And then I copied and pasted the output ISWXACOIOIGKAXHF...
to be the second input. Thus we got ANENIGMAMACHINE
as the second output, which is what we inputed at the beginning.
\documentclass{article}
\usepackage{pgfmath}
% These counters are registers. One needs to assign the initial values of \rotorphasecount
s, which function as the password.
\newcount\crycount
\newcount\plugboardcount
\newcount\rotorcounti
\newcount\rotorcountii
\newcount\rotorcountiii
\newcount\rotorphasecounti
\newcount\rotorphasecountii
\newcount\rotorphasecountiii
\newcount\reflectorcount
% This is the main function. It reads characters until it reaches \end
.
\def\private#1{%
\ifx#1\end
\expandafter\end
\else
% First of all, convert capital letters to numbers. We want A
becomes 0
and Z
becomes 25
.
\crycount`#1
\pgfmathsetmacro\crystringi{int(Mod(\crycount-65,26))}
% Now the number passes through the Plugboard, which is a part of the Enigma.
\plugboard\crystringii\crystringi
% Now the number passes through the three Rotors. It could be four if you want to.
\rotori\crystringiii\crystringii
\rotorii\crystringiv\crystringiii
\rotoriii\crystringv\crystringiv
% Now the number reaches the Reflector.
\reflector\crystringvi\crystringv
% So then the number goes backwards, passing through the Rotors and the Plugboard.
\inverserotoriii\crystringvii\crystringvi
\inverserotorii\crystringviii\crystringvii
\inverserotori\crystringix\crystringviii
\plugboard\crystringx\crystringix
% Convert the number to the hexadecimal code of the corresponding capital letters. For instance 0
means A
, so it should be ^^65
.
\pgfmathsetmacro\crystringxi{hex(\crystringx+65)}
\xdef\crystring{\crystring\string^\string^\crystringxi\string\allowbreak{}}
\expandafter\private
\fi
}
% A Plugboard exchanges pairs of letters. In this case A
and B
are switched. So are C
&D
and E
&F
.
\def\plugboard#1#2{
\plugboardcount#2\xdef#1{\ifcase\plugboardcount1\or0\or3\or2\or5\or4\or6\or7\or8\or9\or10\or11\or12\or13\or14\or15\or16\or17\or18\or19\or20\or21\or22\or23\or24\or25\fi}
}
% A Rotor permutes 26 letters in a fixed way. The funny part is, the first rotor rotates by 2π/26 every time a number passes by. The second rotates every time the first finishes a cycle. And so forth.
\def\rotori#1#2{
\advance\rotorphasecounti1
\pgfmathsetcount\rotorcounti{int(Mod(#2+\rotorphasecounti,26))}
\xdef\rotortexti{\ifcase\rotorcounti1\or2\or3\or4\or0\or6\or7\or8\or9\or10\or11\or12\or13\or14\or15\or16\or17\or18\or19\or20\or21\or22\or23\or24\or25\or5\fi}
\pgfmathsetmacro#1{int(Mod(\rotortexti-\rotorphasecounti,26))}
}
\def\rotorii#1#2{
\ifnum\rotorphasecounti=26\rotorphasecounti0\advance\rotorphasecountii1\fi
\pgfmathsetcount\rotorcountii{int(Mod(#2+\rotorphasecountii,26))}
\xdef\rotortextii{\ifcase\rotorcountii1\or2\or3\or4\or0\or5\or6\or10\or11\or12\or7\or8\or9\or13\or14\or15\or16\or17\or18\or19\or20\or21\or22\or23\or24\or25\fi}
\pgfmathsetmacro#1{int(Mod(\rotortextii-\rotorphasecountii,26))}
}
\def\rotoriii#1#2{
\ifnum\rotorphasecountii=26\rotorphasecountii0\advance\rotorphasecountiii1\fi
\pgfmathsetcount\rotorcountiii{int(Mod(#2+\rotorphasecountiii,26))}
\xdef\rotortextiii{\ifcase\rotorcountiii1\or2\or3\or4\or0\or5\or6\or7\or8\or9\or10\or11\or12\or13\or14\or15\or16\or20\or21\or22\or23\or24\or25\or17\or18\or19\fi}
\pgfmathsetmacro#1{int(Mod(\rotortextiii-\rotorphasecountiii,26))}
}
% The Reflector reflects the number. In the history it always reflected a number to a different one, and that made Enigma self-reciprocal, but unsafe.
\def\reflector#1#2{
\reflectorcount#2\xdef#1{\ifcase\reflectorcount3\or10\or18\or0\or23\or11\or22\or8\or7\or19\or1\or5\or25\or20\or16\or24\or14\or21\or2\or9\or13\or17\or6\or4\or15\or12\fi}
}
% Physically there are only three rotors. But we still need to implement the macro for the opposite direction.
\def\inverserotoriii#1#2{
\pgfmathsetcount\rotorcountiii{int(Mod(#2+\rotorphasecountiii,26))}
\xdef\rotortextiii{\ifcase\rotorcountiii4\or0\or1\or2\or3\or5\or6\or7\or8\or9\or10\or11\or12\or13\or14\or15\or16\or23\or24\or25\or17\or18\or19\or20\or21\or22\fi}
\pgfmathsetmacro#1{int(Mod(\rotortextiii-\rotorphasecountiii,26))}
}
\def\inverserotorii#1#2{
\pgfmathsetcount\rotorcountii{int(Mod(#2+\rotorphasecountii,26))}
\xdef\rotortextii{\ifcase\rotorcountii4\or0\or1\or2\or3\or5\or6\or10\or11\or12\or7\or8\or9\or13\or14\or15\or16\or17\or18\or19\or20\or21\or22\or23\or24\or25\fi}
\pgfmathsetmacro#1{int(Mod(\rotortextii-\rotorphasecountii,26))}
}
\def\inverserotori#1#2{
\pgfmathsetcount\rotorcounti{int(Mod(#2+\rotorphasecounti,26))}
\xdef\rotortexti{\ifcase\rotorcounti4\or0\or1\or2\or3\or25\or5\or6\or7\or8\or9\or10\or11\or12\or13\or14\or15\or16\or17\or18\or19\or20\or21\or22\or23\or24\fi}
\pgfmathsetmacro#1{int(Mod(\rotortexti-\rotorphasecounti,26))}
}
% Now we finish the definition.
\begin{document}
\def\crystring{}
\rotorphasecounti5
\rotorphasecountii8
\rotorphasecountiii13
\begin{private}
AN ENIGMA MACHINE WAS A SERIES OF ELECTRO-MECHANICAL ROTOR CIPHER MACHINES DEVELOPED AND USED IN THE EARLY TO MID TWENTIETH CENTURY FOR COMMERCIAL AND MILITARY USAGE. ENIGMA WAS INVENTED BY THE GERMAN ENGINEER ARTHUR SCHERBIUS AT THE END OF WORLD WAR I.[1] EARLY MODELS WERE USED COMMERCIALLY FROM THE EARLY 1920S, AND ADOPTED BY MILITARY AND GOVERNMENT SERVICES OF SEVERAL COUNTRIES, MOST NOTABLY NAZI GERMANY BEFORE AND DURING WORLD WAR II.[2] SEVERAL DIFFERENT ENIGMA MODELS WERE PRODUCED, BUT THE GERMAN MILITARY MODELS ARE THE MOST COMMONLY RECOGNISED.
\end{private}
\newwrite\cryfile
\immediate\openout\cryfile=\jobname.cry
\immediate\write\cryfile{\crystring}
\immediate\closeout\cryfile
\input{\jobname.cry}
\bigskip
\def\crystring{}
\rotorphasecounti5
\rotorphasecountii8
\rotorphasecountiii13
\begin{private}
ISWXACOIOIGKAXHFCQCQREARUMCRVRFMERXORFOIBAAIVBM UMEFASKWEOIFKABRPWRLRVMSNWQBAOMRWVBUKRMLEYLPUSV WPDNMPVSPKFXMPTULCXUFXKNHUVVBYRQOUBYVJWALMQMBSK SQVBURPBBYLEVLJVZGIJKVBVAURLVLBFLVGPUPJODPMFOVPGYA PUJJOSVLOHCNLPOZNUPYJPSFVUKJNJGZVOKNGSPARPUFLYYUSFW UOJMCSLYQZPGOMJHBZJLUCOXZOZAEQPZGHRWJWNOMHOTZJAX UMURPTNUPMLWWPUADJBLVPOVFAROSUWBOCYAJNTANOEPHTR MCKBAPRFHEBSVABRTZYMAYGNRBAPZARAYYCRKHFBOXARPZYG SBWVHIBHYZWRAVCBJFMXABUGVCPXRCSGPQVNRBMEWZVNVYV QZELWJNSYEZBSVKSWJEQDJKWJXYLBRLMWXTESFK
\end{private}
\newwrite\cryfile
\immediate\openout\cryfile=\jobname.cry
\immediate\write\cryfile{\crystring}
\immediate\closeout\cryfile
\input{\jobname.cry}
\end{document}
Comments
- One can extend the macros so that one can use lower letters or even symbols in their text. At that time one needs to take care of category codes.
- So far the
\rotor
s I implemented are stupid. Because otherwise I have to calculate the \inverserotor
s carefully.
- Enigma is by no means efficient. This is just an illustration of how complex could it be.
Old answer
I would like to propose my approach:
- your ciphertext should be some unicode characters. (So you can compile it by XeLaTeX without password.)
- One guesses the password by setting, say,
\password="2600
.
- For every unicode character,
\password
is subtracted form its code point. For example ♕
=U+2655 becomes 55
- the remaining number is printed to a file with
^^
. That is, ^^55
is printed to a file
- After all unicode characters are processed, the file is
\input
ed. Therefor ♕
finally becomes U
.
Some efforts are left to you:
- Now the decipher function
D(♕,2600)='U'
is quiet simple. You should be able to come up with a better one.
- I am too lazy to pack macros. Do it yourself.
\documentclass{article}
\usepackage{fontspec}
\newcount\password
\newcount\crycount
\newcount\crycounta
\newcount\crycountb
\def\private#1{%
\ifx#1\end
\expandafter\end
\else
\crycount`#1
% ↓↓↓ some math involving \crycount and \password
\advance\crycount-\password
\crycounta\crycount\crycountb\crycount\divide\crycounta16\multiply\crycounta16\advance\crycountb-\crycounta\divide\crycounta16
\xdef\crychara{\ifcase\crycounta0\or1\or2\or3\or4\or5\or6\or7\or8\or9\or a\or b\or c\or d\or e\else f\fi}
\xdef\crycharb{\ifcase\crycountb0\or1\or2\or3\or4\or5\or6\or7\or8\or9\or a\or b\or c\or d\or e\else f\fi}
% ↑↑↑ some math involving \crycount and \password
\xdef\crystring{\crystring\string^\string^\crychara\crycharb}
\expandafter\private
\fi
}
\begin{document}
If key is set to be 2600, you can see the hint below:
\password"2600
\def\crystring{}
\begin{private}
♕♳♥☠♭♡♴♨♥♭♡♴♩♣♡♬☠♩♮♤♵♣♴♩♯♮☠♯♮☠☤♜♬♡♭♢♤♡☤☮
\end{private}
\newwrite\cryfile
\immediate\openout\cryfile=\jobname.cry
\immediate\write\cryfile{\crystring}
\immediate\closeout\cryfile
\input{\jobname.cry}
If key is not 2600, you see random characters:
\password"0
\def\crystring{}
\begin{private}
♕♳♥☠♭♡♴♨♥♭♡♴♩♣♡♬☠♩♮♤♵♣♴♩♯♮☠♯♮☠☤♜♬♡♭♢♤♡☤☮
\end{private}
\newwrite\cryfile
\immediate\openout\cryfile=\jobname.cry
\immediate\write\cryfile{\crystring}
\immediate\closeout\cryfile
\input{\jobname.cry}
\end{document}
Best Answer
The problem you are having is that
\Sexpr
cannot be nested because of how R evaluates and how LaTeX evaluates. But I have implemented what I think you want.Based upon your revision, the conditional must be all done inside of R, as follows:
And the result is: