Re: Mathematics of the Enigma cipher?
- From: "mensanator@xxxxxxx" <mensanator@xxxxxxx>
- Date: 1 Jan 2007 18:06:01 -0800
DarkProtoman wrote:
mensanator@xxxxxxx wrote:
DarkProtoman wrote:
<snip physics debate>
What about the original topic? How do I write the decrypt function for
this encrypt function:
I think this is wrong. I'm not an expert in C++ and even if I was,
I can't test it since this is not your complete code. But my first
attempt at Python didn't work and this looks very much like
my code when it was incorrect.
string Enigma::Encrypt(const string& cleartext)
{
string ciphertext;
ciphertext.resize(cleartext.size());
int i=0;
for(;i<cleartext.length();i++)
{
int val=Rotor::CharacterMap(cleartext[i]);
char val1=R1.GetCharacterIndex(val);
A character is mapped to an integer which becomes
the index to the Rotor. So far so good.
R1.AdvanceRotor((i+1)%36);
I think you're doing this wrong. All the Rotors should be advanced
before the first character is read (in mine, I spun them after I read
them but that is not relevant, the rotors are supposed to remain
stationary until the clear character is converted to a cipher
character).
int val2=Rotor::CharacterMap(val1);
char val3=R2.GetCharacterIndex(val2);
if(R1.GetSteps()==36)
R2.ReverseRotor((i+1)%36);
int val4=Rotor::CharacterMap(val3);
char val5=R3.GetCharacterIndex(val4);
if(R2.GetSteps()==-36)
R3.AdvanceRotor((i+1)%36);
int val6=Rotor::CharacterMap(val5);
char val7=R4.GetCharacterIndex(val6);
if(R3.GetSteps()==36)
R4.ReverseRotor((i+1)%36);
int val8=Rotor::CharacterMap(val7);
char val9=R5.GetCharacterIndex(val8);
if(R4.GetSteps()==-36)
R5.AdvanceRotor((i+1)%36);
int val10=Rotor::CharacterMap(val9);
char val11=Ref.GetCharacterIndex(val10);
I assume Ref is the Reflector.
if(R5.GetSteps()==36)
Ref.ReverseRotor((i+1)%36);
I thought the Reflector was fixed.
int val12=Rotor::CharacterMap(val11);
char val13=R5.GetCharacterIndex(val12);
Now it appears that you're taking the refelected character
and passing it back through the rotors without advancing
them (which is correct, but you shouldn't have been advancing
them during the forwards pass either. All Rotors should
be advanced before the first character is read).
BUT...
You do not appear to be doing the inverse of reading the
Rotors on the backwards pass from R5 to R1. If you were
to remove the reflector, a correct backwards pass would
return the original clear character.
That's not going to happen here. Suppose the effect of the
Rotors was to simply shift a character one step forwards.
The reflected character then should shift a character one step
backwards. Without a Reflector, you would see:
clear R1 R2 R3 R4 R5 R5 R4 R3 R2 R1 cipher
A -> B -> C -> D -> E -> F -> F -> E -> D -> C -> B -> A
But your code appears to simply be doing the forwards algorithm
on the reflected character which would give you:
clear R1 R2 R3 R4 R5 R5 R4 R3 R2 R1 cipher
A -> B -> C -> D -> E -> F -> G -> H -> I -> J -> K -> L
When you put back the actual Reflector, you'll get a different
cipher letter but you won't be able to decode it because when
you enter the cipher character, you'll get a different cipher
character output and not the original clear character.
int val14=Rotor::CharacterMap(val13);
char val15=R4.GetCharacterIndex(val14);
int val16=Rotor::CharacterMap(val15);
char val17=R3.GetCharacterIndex(val16);
int val18=Rotor::CharacterMap(val17);
char val19=R2.GetCharacterIndex(val18);
int val20=Rotor::CharacterMap(val19);
char val21=R1.GetCharacterIndex(val20);
ciphertext[i]=plugboard(val21);
}
return ciphertext;
}
Here's what I've got so far:
I predict this will fail. You need a function that given a
character, finds what index it occurs at on R5, and pass that
to R4.
Test it by removing the Reflector. If it's correct, the cipher
should come back the same as the clear. Then, when you put back
the Reflector, you'll get a proper cipher. And you won't even
need a decoder, you just set the rotors to the same state you
used to encode the clear and call the encode function with the
cipher. You'll get back the clear.
string Enigma::Decrypt(const string& ciphertext)
{
string cleartext;
cleartext.resize(ciphertext.size());
int i=0;
for(;i<ciphertext.length();i++)
{
char val1=plugboard(ciphertext[i]);
char val2=R1.GetCharacterIndex(val1);
int val3=Rotor::CharacterMap(val2);
char val4=R2.GetCharacterIndex(val3);
int val5=Rotor::CharacterMap(val4);
char val6=R3.GetCharacterIndex(val5);
int val7=Rotor::CharacterMap(val6);
char val8=R4.GetCharacterIndex(val7);
int val9=Rotor::CharacterMap(val8);
char val10=R5.GetCharacterIndex(val9);
int val11=Rotor::CharacterMap(val10);
//not done
}
}
OK, here's the Rotor and Enigma classes:
<snip code>
Thanks, I won't have time tonight to run it (got to figure out
how to use C++ first).
How do I write a fn that given a character, it'll find the index? It
still doesn't decrypt by encrypting twice.
Just to make sure I'm not putting my foot in my mouth, I re-wrote
my Python program to use 5 rotors and a Reflector (no plug-board,
but that isn't relavent here). I implemented the Reflector as a
dictionary using random encodings that are invertable, i.e.,
a -> c, c -> a.
And now I send a character through the rotors forwards, reflect
it, and send it through the rotors backwards to become the cipher.
With the Reflector disabled (character is reflected unchanged),
I do indeed get a cipher that equals the plain text.
## Plain text:
##
## four score and seven years ago
## our fathers brought forth on this
## continent a new nation conceived
## in liberty and dedicated to the
## proposition that all men are
## created equal.
##
## Encoded: (without Reflector - s/b same as plain)
##
## four score and seven years ago
## our fathers brought forth on this
## continent a new nation conceived
## in liberty and dedicated to the
## proposition that all men are
## created equal.
After verifying that this works as predicted, I simply enable the
Reflector to get actual cipher text:
## Plain text:
##
## four score and seven years ago
## our fathers brought forth on this
## continent a new nation conceived
## in liberty and dedicated to the
## proposition that all men are
## created equal.
##
##
## Encoded:
##
## iq5q 3hno9 5a1 gclf0 1pb3p lt0
## l7o 4nhthfn n3jhtc3 azw6t ts isfi
## bdcy6qdzo b q3r kco5cb hmlhrk821
## jx it6dp53 9ln idcgp9ocb vt r4j
## nq0on2dsuyx vkcj 8y9 ood xur
## bognh43 qevdg.
And finally, all I have to do to decode it is encode the cipher
with the same Rotor starting positions used to encode it the
first time. No need anymore for a seperate decode function:
## Decoded:
##
## four score and seven years ago
## our fathers brought forth on this
## continent a new nation conceived
## in liberty and dedicated to the
## proposition that all men are
## created equal.
Voila.
Now, as to how _you_ can do this, well, I'm not familiar with
what can be done in C++, although the concept is relatively simple.
I'll explain it in terms of Python and hopefully you can figure
out how to do the same thing in C++.
Think of a Python list as an array.
So if I have a list R = [3, 4, 5, 0, 1, 2] then
R[2] = 5 (since indexing is from 0).
Now if the value that comes out of the Reflector is 5, I need
know what the index is on R5 that gives me a 5 because that's
what I have to pass back to R4. In the example, the index is 2.
In Python, I can simply say
i = R5.index(5)
because this is a very useful method for arrays and is part of
the language. You want to see if C++ has something similar. If not,
you probably want to add that as a method to your Rotor class (but
be sure the index is relative to the current Rotor position. I do
rotation by popping and appending the list so that absolute index
is always the same as relative index).
If it wasn't already built in, I'd do something like
p = Reflector[o]
i = 0
while R5[i] != p: i += 1
When I exit the loop, i=2 and now I pass that back to R4.
The Python code looks like
def encode(a):
# test decoding by disabling the Reflector in which case
# the cipher should equal the plain text
spin_rotors() # actual Enigma spins rotors first
aa = int(a,36) # convert base 36 char to int
i = R1[aa] # R1 is index to R2
j = R2[i] # R2 is index to R3
k = R3[j] # R3 is index to R4
m = R4[k] # R4 is index to R5
n = R5[m] # R5 is the encoded value (forward)
o = gmpy.digits(n,36) # convert to base 36 char
p = Reflector[o] # and reflect it
#p = o # or not (test)
q = int(p,36) # convert reflected base36 char to int
r = R5.index(q) # index of R5 where this is found
s = R4.index(r) # repeat for other rotors
t = R3.index(s)
u = R2.index(t)
v = R1.index(u) # R1 is the encoded value (backwards)
w = gmpy.digits(v,36) # convert to base 36 char
return w # to become the cipher
If you still can't make any sense of this, I'll try to get
your program to run and see what I can do with it. That will be
more interesting than arguing with Richard about the speed of
electricity.
.
- Follow-Ups:
- Re: Mathematics of the Enigma cipher?
- From: DarkProtoman
- Re: Mathematics of the Enigma cipher?
- References:
- Re: Mathematics of the Enigma cipher?
- From: mensanator@xxxxxxx
- Re: Mathematics of the Enigma cipher?
- From: Richard Heathfield
- Re: Mathematics of the Enigma cipher?
- From: mensanator@xxxxxxx
- Re: Mathematics of the Enigma cipher?
- From: Richard Heathfield
- Re: Mathematics of the Enigma cipher?
- From: DarkProtoman
- Re: Mathematics of the Enigma cipher?
- From: mensanator@xxxxxxx
- Re: Mathematics of the Enigma cipher?
- From: DarkProtoman
- Re: Mathematics of the Enigma cipher?
- Prev by Date: Re: Mathematics of the Enigma cipher?
- Next by Date: Re: removal of recursion in binary tree
- Previous by thread: Re: Mathematics of the Enigma cipher?
- Next by thread: Re: Mathematics of the Enigma cipher?
- Index(es):
Relevant Pages
|