DIY Rotorchiffer/Subsitutionschiffer i Python

Berätta om dina pågående projekt.
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av Shimano »

Förr i tiden(före digitalelektronikens tid) så användes mekaniska skiffer av olika sorter, ett exempel är tyskarnas enigma, ett annat är det ryska Fialka. Dessa fungerade i princip på samma sätt, ett antal rotorer som var länkade på olika sätt och ställdes i olika possitioner beroende på vilken nyckel man ville använda. Enigma maskinen hade faktiskt en nyckelstorlek på 80bitar har jag för mig.

Idag görs säkert skiffer på bättre och säkrare sätt, men det hade varit roligt att göra ett eget skiffer, man är ju inte längre begränsad av mekaniken i rullarna som kan kärva tex. Jag har lyckats göra detta i Pyhton, med 3st rotorer så får man en nyckel på runt 14-bitar, men fler är ju inte något problem att lägga till.

Programmet är enkelt. Varje rotor länkar in i en "rotor"(int array) på possitionen i arrayen, och ut på värdet. Därefter går den in i nästa osv... när variabeln gått ut ur den sista, C-rotorn, så snurras första rotorn ett klick, andra 2, och tredje 3.

Jag är inte någon mästa på varesig python eller skiffer som ni säkert förstår, men det verkade vara ett roligt projekt.

Kritik mottages gärna!(helst possitiv iofs...) :rofl

Något gör så att den avkodade arrayen ibland skiljer sig på någon siffra, ibland inte, beroende på nyckeln....

Bild

Kod: Markera allt


import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [12,24,1,3,11,4,7,21,19,22,6,16,20,14,15,26,9,10,25,5,13,23,2,8,17,18])
b = arr.array('l', [20,9,3,22,19,21,14,5,17,2,26,12,23,25,10,8,18,6,24,15,16,1,7,4,11,13])
c = arr.array('l', [21,19,4,16,26,18,2,12,8,11,14,20,3,13,24,23,25,1,15,10,9,17,22,5,7,6])

#Krypteringsnyckeln
key = arr.array('l', [1,9,7])

#Meddelandet som ska kodas
msg = arr.array('l', [3, 17, 12, 22])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]
PosC = key[2]
#skriv ut meddelandet
print(msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%26
  outbyte = a[PosY-1]
    
  PosX = (PosB+outbyte)%26
  outbyte = b[PosX-1]
  
  PosZ = (PosC+outbyte)%26
  outbyte = c[PosZ-1]
  
  #Rotera hjulen
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  enc[x] = outbyte
  
print(enc)

#Dekryptering
PosA = key[0]
PosB = key[1]
PosC = key[2]

for y in range(4):
#Avkoda genom C
  for x in range(25):
    if c[x] == enc[y]:
     # print((x+1-PosC)%26)
      valC = (x+1-PosC)%26
#Avkoda genom B
  for x in range(25):
    if b[x] == valC:
      #print((x+1-PosB)%26)
      valB = (x+1-PosB)%26
#Avkoda genom A
  for x in range(25):
    if a[x] == valB:
      valA = (x+1-PosA)%26
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  dec[y] = valA
print(dec)

Senast redigerad av Shimano 13 maj 2019, 07:52:42, redigerad totalt 2 gånger.
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av Shimano »

Jag har lagt in 10st rotorer, med vardera 29st possitioner. Det ger en nyckelstorlek på 48-bitar. Däremot funkar inte avkodningen korrekt, det är förmodligen något med hur jag räknar ut modulen. När possitionen på en rotor dras av från den nuvarnade possitionen, dvs om rotorn står på 15 och ska backa 20, så ska nästa position vara 29-5, dvs 24. och inte -5.



Kod: Markera allt

import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [12,24,1,3,11,4,7,21,19,22,28,6,16,20,14,27,15,26,9,10,25,29,5,13,23,2,8,17,18])
b = arr.array('l', [20,27,9,3,22,19,21,14,5,28,17,2,26,12,23,25,10,29,8,18,6,24,15,16,1,7,4,11,13])
c = arr.array('l', [21,19,4,16,26,18,2,12,8,11,27,14,28,20,3,13,24,23,25,1,15,10,29,9,17,22,5,7,6])
d = arr.array('l', [1,17,29,28,9,22,24,21,15,25,20,23,2,27,14,18,5,26,3,8,10,6,16,7,13,19,4,12,11])
e = arr.array('l', [20,21,14,27,10,5,3,26,16,4,23,28,25,11,17,24,8,12,18,15,29,2,13,1,9,19,7,22,6])
f = arr.array('l', [15,7,23,17,28,5,24,3,6,1,25,22,27,2,20,12,13,10,16,29,26,9,8,4,11,21,19,18,14])
g = arr.array('l', [14,15,12,17,2,21,9,16,24,25,22,20,23,11,8,10,4,1,18,26,27,28,29,3,6,13,19,5,7])
h = arr.array('l', [12,22,20,13,27,17,11,14,5,6,29,16,9,21,2,8,7,4,24,18,28,15,3,10,23,1,25,19,26])
i = arr.array('l', [5,1,24,22,18,9,11,12,4,21,16,6,7,27,17,20,2,26,25,28,14,8,15,13,29,10,3,19,23])
j = arr.array('l', [7,6,19,12,27,18,5,4,1,16,15,28,9,26,22,13,23,11,3,25,17,14,29,8,21,24,20,2,10])

#Krypteringsnyckeln
key = arr.array('l', [10,9,17,2,1,5,1,20,13,5])

#Meddelandet som ska kodas
msg = arr.array('l', [5,23, 14, 8])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]
PosC = key[2]
PosD = key[3]
PosE = key[4]
PosF = key[5]
PosG = key[6]
PosH = key[7]
PosI = key[8]
PosJ = key[9]

#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosAb = (PosA+msg[x])%29
  outbyte = a[PosAb-1]
    
  PosBb = (PosB+outbyte)%29
  outbyte = b[PosBb-1]
  
  PosCb = (PosC+outbyte)%29
  outbyte = c[PosCb-1]
  
  PosDb = (PosD+msg[x])%29
  outbyte = d[PosDb-1]
    
  PosEb = (PosE+outbyte)%29
  outbyte = e[PosEb-1]
  
  PosFb = (PosF+outbyte)%29
  outbyte = f[PosFb-1]
  
  PosGb = (PosG+msg[x])%29
  outbyte = g[PosGb-1]
    
  PosHb = (PosH+outbyte)%29
  outbyte = h[PosHb-1]
  
  PosIb = (PosI+outbyte)%29
  outbyte = i[PosIb-1]
  
  PosJb = (PosJ+outbyte)%29
  outbyte = j[PosJb-1]
  
  
  #Rotera hjulen
  PosA = PosA + 1
  PosB = PosB + 3
  PosC = PosC + 1
  PosD = PosD + 4
  PosE = PosE + 5
  PosF = PosF + 2
  PosG = PosG + 3
  PosH = PosH + 6
  PosI = PosI + 2
  PosJ = PosJ + 3
  
  enc[x] = outbyte

#Skriv ut det krypterade meddelandet
print('Krypterad: ',enc)

#Dekryptering
PosA = key[0]
PosB = key[1]
PosC = key[2]
PosD = key[3]
PosE = key[4]
PosF = key[5]
PosG = key[6]
PosH = key[7]
PosI = key[8]
PosJ = key[9]

for y in range(4):
#Avkoda genom j
  for x in range(28):
    if j[x] == enc[y]:
      valJ = (x+1-PosJ)%29
      print('In:',j[x])
      print('J:',valJ)
#Avkoda genom i
  for x in range(28):
    if i[x] == valJ:
      valI = (x+1-PosI)%29
      print('I: ',valI)
#Avkoda genom h
  for x in range(28):
    if h[x] == valI:
      valH = (x+1-PosH)%29
      print('H: ',valH)
#Avkoda genom g
  for x in range(28):
    if g[x] == valH:
      valG = (x+1-PosG)%29
      print('G: ',valG)
#Avkoda genom f
  for x in range(28):
    if f[x] == valG:
      valF = (x+1-PosF)%29
      print('F: ',valF)
#Avkoda genom e
  for x in range(28):
    if e[x] == valF:
      valE = (x+1-PosE)%29
      print('E: ',valE)
#Avkoda genom d
  for x in range(28):
    if d[x] == valE:
      valD = (x+1-PosD)%29
      print('D: ',valD)
#Avkoda genom c
  for x in range(28):
    if c[x] == valD:
      valC = (x+1-PosC)%29
      print('C: ',valC)
#Avkoda genom b
  for x in range(28):
    if b[x] == valC:
      valB = (x+1-PosB)%2
      print('B: ',valB)
#Avkoda genom a
  for x in range(28):
    if a[x] == valB:
      valA = (x+1-PosA)%29
      print('A',valA)

  PosA = PosA + 1
  PosB = PosB + 3
  PosC = PosC + 1
  PosD = PosD + 4
  PosE = PosE + 5
  PosF = PosF + 2
  PosG = PosG + 3
  PosH = PosH + 6
  PosI = PosI + 2
  PosJ = PosJ + 3
  dec[y] = valA
print(dec)
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av guckrum »

Förslag: Försök göra listor av listor (matriser) så slipper du upprepa kod. Filen blir mycket kortare, koden blir generell och funkar för N rotorer, och det är mindre risk för fel och dessutom enklare att felsöka.
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av Shimano »

Felet verkar inträffa när man dekrypterar och spårar baklänges genom rotorerna och får 0, då stoppar allting eftersom variabeln inte känns igen...
  • Kod: Markera allt

    Meddelande:  array('l', [5, 23, 14, 8])
    Krypterad:  array('l', [13, 25, 13, 5])
    In: 13
    J: 10
    I:  12
    H:  9
    G:  5
    F:  0
    Traceback (most recent call last):
      File "main.py", line 133, in <module>
        if d[x] == valE:
    NameError: name 'valE' is not defined
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av guckrum »

Jag förstod det som att du ville ha feedback. Jobba på bara!

Istället för

Kod: Markera allt

a = arr.array('l', [12,24,1,3,11,4,7,21,19,22,6,16,20,14,15,26,9,10,25,5,13,23,2,8,17,18])
b = arr.array('l', [20,9,3,22,19,21,14,5,17,2,26,12,23,25,10,8,18,6,24,15,16,1,7,4,11,13])
c = arr.array('l', [21,19,4,16,26,18,2,12,8,11,14,20,3,13,24,23,25,1,15,10,9,17,22,5,7,6])
kan du göra typ såhär:

Kod: Markera allt

c = [
  [12,24,1,3,11,4,7,21,19,22,6,16,20,14,15,26,9,10,25,5,13,23,2,8,17,18],
  [20,9,3,22,19,21,14,5,17,2,26,12,23,25,10,8,18,6,24,15,16,1,7,4,11,13],
  [21,19,4,16,26,18,2,12,8,11,14,20,3,13,24,23,25,1,15,10,9,17,22,5,7,6],
]
och addressera c[rad][kolumn], tex är c[1,3] = 22. Då får du bara en variabel
för alla kodhjulen. Antalet kodhjul är alltså len(c).

Som du ser har jag också valt att använda Pythons "list"-typ istället för "array",
jag tycker det är bra nog.
Användarvisningsbild
farbrorvattenmelon
Inlägg: 255
Blev medlem: 29 januari 2009, 21:38:21

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av farbrorvattenmelon »

Tack för att du delade koden!
Har inte tänkt något på själva krypteringen, däremot några förslag kring kodandet.


Ser förslag om att skippa array och köra på listor, vilket jag håller med om, kanske rent av tuples?

Guckrums råd att lägga alla hjul i någon bättre form och loopa genom dem låter också bra.
Kanske få lite mer människoläsbar kod med bättre variabelnamn och loopar typ:

Kod: Markera allt

for wheel in rotors:
   decrypt(input)
EDIT:

Kod: Markera allt

PosA = PosA + 1
Detta gör du snyggare genom

Kod: Markera allt

PosA += 1
EDIT2:
Använd index-funktionen för listor så slipper du göra egna loopar för att leta efter värden...
Senast redigerad av farbrorvattenmelon 12 maj 2019, 21:16:13, redigerad totalt 2 gånger.
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av guckrum »

ja, precis, tuplar är ju bättre (eftersom de är "immutable", dvs
mera som konstanter, vilket ju är applikationen här). Det spelar
ingen roll här, men det är bra "design practice" att använda tuplar
framför listor så ofta man kan. Snabbare blir det också. Tack.
Användarvisningsbild
farbrorvattenmelon
Inlägg: 255
Blev medlem: 29 januari 2009, 21:38:21

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av farbrorvattenmelon »

Ge oss exempel på några meddelanden i klartext, nyckel och önskat resultat efter kryptering.
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av Shimano »

Tack för tipsen! Jag började använda listor, men fick problem med dom eftersom efterföljande programbitar inte godkände dessa som integer, det enklaste lösningen jag hittade var att göra dom till arrayer istället. Om ni inte har Python installerat, testa på https://repl.it/, det är den utvecklingsmiljön jag använder.

Jag har fått gå tillbaka några steg för att försöka hitta felet, vissa krypteringsnycklar fungerar medans andra inte gör det. Nedan fungerar bra, men om jag ändrar nyckeln från 9,7,1 till 9,8,1 så havererar programmet vid avkodningen. Det är när siffran 0 kommer in i bilden, men jag förstår inte riktigt varför det skulle vara ett problem.


Kod: Markera allt

import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [0,1,4,3,8,7,6,2,5,9])
b = arr.array('l', [6,1,9,3,4,8,2,5,7,0])
c = arr.array('l', [9,2,6,3,8,1,4,7,0,5])

#Krypteringsnyckeln
key = arr.array('l', [9,7,1])
#Meddelandet som ska kodas
msg = arr.array('l', [3, 1, 8, 7])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]
PosC = key[2]
#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%9
  outbyte = a[PosY]
    
  PosX = (PosB+outbyte)%9
  outbyte = b[PosX]
  
  PosZ = (PosC+outbyte)%9
  outbyte = c[PosZ]
  
  #Rotera hjulen
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  enc[x] = outbyte
  
print('Krypterat: ',enc)

#Dekryptering
PosA = key[0]
PosB = key[1]
PosC = key[2]

for y in range(4):
#Avkoda genom C
  for x in range(9):
    if c[x] == enc[y]:
     # print((x+1-PosC)%26)
      valC = (x-PosC)%9
      print('C: ',valC)
#Avkoda genom B
  for x in range(9):
    if b[x] == valC:
      #print((x+1-PosB)%26)
      valB = (x-PosB)%9
      print('B: ',valB)
#Avkoda genom A
  for x in range(9):
    if a[x] == valB:
      valA = (x-PosA)%9
      print('A: ',valA)
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  dec[y] = valA
print("Dekrypterat: ",dec)
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorskiffer/Subsitutionsskiffer i Python

Inlägg av Shimano »

Felet är svårt att hitta, när jag förenklar programmet till 2st rotorer så fungerar det felfritt, även samma mekanism som inte fungerade med 3st rotorer.

Problemet inträffar när utgången ur en rotor hamnar på 0, detta funkar med 2st rotorer men inte med fler, varför är oklart. Koden nedan klarar det utan problem, med 2st rotorer. Men så fort man lägger på en tredje rotor så fungerar det inte längre, även dom delar som fungerade tidigare och inte borde påverkas.

Kod: Markera allt

import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [0,1,4,3,8,7,6,2,5,9])
b = arr.array('l', [6,1,9,3,4,8,2,5,7,0])

#Krypteringsnyckeln
key = arr.array('l', [1,1])
#Meddelandet som ska kodas
msg = arr.array('l', [3, 1, 8, 7])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]

#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%9
  outbyte = a[PosY]
    
  PosX = (PosB+outbyte)%9
  outbyte = b[PosX]
  
  #PosZ = (PosC+outbyte)%9
  #outbyte = c[PosZ]
  
  enc[x] = outbyte
  
print('Krypterat: ',enc)

#Dekryptering
PosA = key[0]
PosB = key[1]


for y in range(4):
#Avkoda genom C
#  for x in range(9):
#    if c[x] == enc[y]:
#      print(x)
#     # print((x+1-PosC)%26)
#      valC = (x-PosC)%9
#      print('C: ',valC)
#Avkoda genom B
  for x in range(9):
    if b[x] == enc[y]:
      print(x)
      #print((x+1-PosB)%26)
      valB = (x-PosB)%9
      print('B: ',valB)
#Avkoda genom A
  for x in range(9):
    if a[x] == valB:
      print(x)
      valA = (x-PosA)%9
      print('A: ',valA)
  dec[y] = valA
print("Dekrypterat: ",dec)
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av johano »

Det första felet är att "range" returnerar _upp till_ men inte _inklusive_

Kod: Markera allt

for x in range(9):
    print(x)
ger alltså 0,1,2,3,4,5,6,7,8 MEN INTE 9

Och då blir aldrig valB tilldelad med kodnyckeln (9,8,1) och programmet kraschar följdaktligen.

Sen finns det andra (logiska) fel som gör att det dekrypterade meddelandet inte blir rätt
med kodnyckeln (9,8,1) men det orkar jag inte felsöka nu :-)

/johan
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av Shimano »

Bra att du hittade ett fel, tack! Där är fortfarande något som gör att när koden letar sig genom kodhjulen och 0:an blir invald så blir avkodningen felaktig av någon anledning. Men koden krashar åtminstone inte längre :)

Bild

Kod: Markera allt

import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [0,1,4,3,8,7,6,2,5,9])
b = arr.array('l', [6,1,9,3,4,8,2,5,7,0])
c = arr.array('l', [9,2,6,3,8,1,4,7,0,5])

#Krypteringsnyckeln
key = arr.array('l', [9,8,1])
#Meddelandet som ska kodas
msg = arr.array('l', [3, 1, 8, 7])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]
PosC = key[2]
#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%9
  outbyte = a[PosY]
    
  PosX = (PosB+outbyte)%9
  outbyte = b[PosX]
  
  PosZ = (PosC+outbyte)%9
  outbyte = c[PosZ]
  
  #Rotera hjulen
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  enc[x] = outbyte
  
print('Krypterat: ',enc)

#Dekryptering
PosA = key[0]
PosB = key[1]
PosC = key[2]

for y in range(4):
#Avkoda genom C
  for x in range(10):
    if c[x] == enc[y]:
     # print((x+1-PosC)%26)
      valC = (x-PosC)%9
      print('C: ',valC)
#Avkoda genom B
  for x in range(10):
    if b[x] == valC:
      #print((x+1-PosB)%26)
      valB = (x-PosB)%9
      print('B: ',valB)
#Avkoda genom A
  for x in range(10):
    if a[x] == valB:
      valA = (x-PosA)%9
      print('A: ',valA)
  PosA = PosA + 1
  PosB = PosB + 2
  PosC = PosC + 3
  dec[y] = valA
print("Dekrypterat: ",dec)
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av Shimano »

Jag har nu provat med ett stillastående chiffer(rotorerna snurrar inte), och felet verkar vara hittat. Det handlar om hur "modulen" räknas runt rotorn. Denna blir något förskjuten om den passerar 0, därför får man fel avkodning. Så länge det blir samma fel vid på och avkodning så märks det inte.

Första värdet som ska kodas är 3, det går in på plats nummer 3 i hjul A, + 2(nyckeln). Värdet på plats 5 är 7, dvs ut ur hjul A kommer värde 7.

Plats 7 på hjul B + 6(nyckeln) är 3, men programmet tror att det är en 4:a. Som "tur är" så råkar det med denna nyckel bli samma fel vid avkodning, så det funkar just i detta fallet.

Om jag ökar modulberäkningen till att modulera över 10 så verkar det funka, ska prova och se om jag kan ändra detta i den stora koden!


Bild

Kod: Markera allt


import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [0,1,4,3,8,7,6,2,5,9])
b = arr.array('l', [6,1,9,3,4,8,2,5,7,0])
c = arr.array('l', [9,2,6,3,8,1,4,7,0,5])

#Krypteringsnyckeln
key = arr.array('l', [2,14,1])
#Meddelandet som ska kodas
msg = arr.array('l', [3, 1, 8, 7])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = key[0]
PosB = key[1]
PosC = key[2]
#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%10
  outbyte = a[PosY]
  
  print('Ut A:', outbyte)
    
  PosX = (PosB+outbyte)%10
  outbyte = b[PosX]
  
  print('Ut B:', outbyte)

  PosZ = (PosC+outbyte)%10
  outbyte = c[PosZ]
  
  print('Ut C:', outbyte)
  #Rotera hjulen
  print()
  enc[x] = outbyte
  
print('Krypterat: ',enc)

#Dekryptering
PosA = key[0]
PosB = key[1]
PosC = key[2]

for y in range(4):
#Avkoda genom C
  for x in range(10):
    if c[x] == enc[y]:
     # print((x+1-PosC)%26)
      valC = (x-PosC)%10
      print('C: ',valC)
#Avkoda genom B
  for x in range(10):
    if b[x] == valC:
      #print((x+1-PosB)%26)
      valB = (x-PosB)%10
      print('B: ',valB)
#Avkoda genom A
  for x in range(10):
    if a[x] == valB:
      valA = (x-PosA)%10
      print('A: ',valA)
      print()
  dec[y] = valA
print("Dekrypterat: ",dec)
Efter ändringen till modul 10:

Bild
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av guckrum »

En alternativ lösning kodad på hög nivå är att enkapsulera all hjul-funktionalitet i en hjul-klass, och sedan instantiera ett objekt av den per hjul. Mycket lättare att testa och felsöka.
Shimano
Inlägg: 40
Blev medlem: 22 april 2019, 13:13:05

Re: DIY Rotorchiffer/Subsitutionschiffer i Python

Inlägg av Shimano »

Nu har jag lyckats få koden att funka! :D Felen var som någon påpekade att jag hade missat for range funktionens ändläge, och missbedömt hur stora jag skulle göra modolus på hjulen. Som koden är skriven nu använder man 10st hjul med vardera 29 possitioner(primtal för att rotationen inte ska jag att ett begränsat antal positioner används). Det ger 4,2*10^14 möjliga nycklar, vilket motsvarar 48-bitar i nyckelstorlek ungefär.

För att öka antalet möjliga nycklar verkar ryssarna och tyskarna på sina enigma/faikla maskiner ha gjort så att hjulen kan flyttas i ordning, på min "maskin" finns det 10 hjul med lika många platser, vilket borde göra att man skulle kunna få 3,6miljoner möjliga kombinationer. Använder man detta så får man totalt 1,5*10^21 möjliga nycklar vilket är strax under 72-bitar, vilket nog kan betraktas som en säker nyckel.

Ett annat alternativ är att ändra hur hjulen roterar, dvs hur många steg dessa tar efter varje kodning. Om man kan välja att varje hjul ska ta mellan 1 och 10 steg efter varje kodat tecken, så borde det finnas 10 miljarder olika möjligheter, vilket tillsammans med hjulens startpositioner skulle ge 2,4*10^24 möjliga nycklar, 80-bitar.

Jag har valt att gå på den sistnämnda modellen, krypteringsnycklarna är därför nu uppdelade i en "meddelandenyckel" och en "pin nyckel" som avgör hur mycket hjulen snurrar efter varje tecken.

Kod: Markera allt

import array as arr
#Detta är dom fyra kodhjulen
a = arr.array('l', [12,24,16,3,11,4,7,21,19,22,6,1,20,14,15,26,9,10,25,5,13,23,2,8,17,18,0,27,28])
b = arr.array('l', [4,9,18,10,8,13,24,7,5,2,22,28,14,27,3,1,25,11,26,20,0,19,6,15,16,21,23,12,17])
c = arr.array('l', [10,14,4,11,28,25,26,17,5,21,27,23,0,13,18,24,7,1,15,22,20,16,2,6,8,9,3,19,12])
d = arr.array('l', [28,6,21,19,1,22,18,10,7,3,14,11,27,15,16,0,8,20,24,25,5,9,23,2,17,13,26,4,12])
e = arr.array('l', [10,6,24,13,9,25,3,16,23,8,19,15,22,12,21,17,5,1,18,28,7,2,11,0,20,14,4,26,27])
f = arr.array('l', [1,11,27,17,7,13,16,21,2,24,23,12,4,20,19,15,6,25,14,10,0,18,8,5,22,26,9,28,3])
g = arr.array('l', [12,24,16,3,11,4,7,21,19,22,6,1,20,14,15,26,9,10,25,5,13,23,2,8,17,18,0,27,28])
h = arr.array('l', [4,9,18,10,8,13,24,7,5,2,22,28,14,27,3,1,25,11,26,20,0,19,6,15,16,21,23,12,17])
i = arr.array('l', [28,6,21,19,1,22,18,10,7,3,14,11,27,15,16,0,8,20,24,25,5,9,23,2,17,13,26,4,12])
j = arr.array('l', [1,11,27,17,7,13,16,21,2,24,23,12,4,20,19,15,6,25,14,10,0,18,8,5,22,26,9,28,3])

#Meddelandenyckel
msgkey = arr.array('l', [2,5,21,3,16,3,22,13,8,25])
#Meddelandenyckel
pinkey = arr.array('l', [1,5,10,4,6,3,2,10,9,2])
#Meddelandet som ska kodas
msg = arr.array('l', [3, 1, 8, 28])
#det krypterade meddelandet
enc = arr.array('l',[1,1,1,1])
#det dekrypterade meddelandet
dec = arr.array('l',[1,1,1,1])
#Kodinställning, startpossition per hjul
PosA = msgkey[0]
PosB = msgkey[1]
PosC = msgkey[2]
PosD = msgkey[3]
PosE = msgkey[4]
PosF = msgkey[5]
PosG = msgkey[6]
PosH = msgkey[7]
PosI = msgkey[8]
PosJ = msgkey[9]

#skriv ut meddelandet
print('Meddelande: ',msg)
#Kyptering
for x in range(4):
  PosY = (PosA+msg[x])%29
  outbyte = a[PosY]
  PosX = (PosB+outbyte)%29
  outbyte = b[PosX]
  PosZ = (PosC+outbyte)%29
  outbyte = c[PosZ]
  PosY1 = (PosD+outbyte)%29
  outbyte = d[PosY1]
  PosY2 = (PosE+outbyte)%29
  outbyte = e[PosY2]
  PosY3 = (PosF+outbyte)%29
  outbyte = f[PosY3]
  PosY4 = (PosG+outbyte)%29
  outbyte = g[PosY4]
  PosY5 = (PosH+outbyte)%29
  outbyte = h[PosY5]
  PosY6 = (PosI+outbyte)%29
  outbyte = i[PosY6]
  PosY7 = (PosJ+outbyte)%29
  outbyte = j[PosY7]
  enc[x] = outbyte
  
  #Rotering av hjul, efter pinkey.
  PosA = PosA + pinkey[0]
  PosB = PosB + pinkey[1]
  PosC = PosC + pinkey[2]
  PosD = PosD + pinkey[3]
  PosE = PosE + pinkey[4]
  PosF = PosF + pinkey[5]
  PosG = PosG + pinkey[6]
  PosH = PosH + pinkey[7]
  PosI = PosI + pinkey[8]
  PosJ = PosJ + pinkey[9]
  
print('Krypterat: ',enc)

#Dekryptering, börja med att nollställa nyckeln
PosA = msgkey[0]
PosB = msgkey[1]
PosC = msgkey[2]
PosD = msgkey[3]
PosE = msgkey[4]
PosF = msgkey[5]
PosG = msgkey[6]
PosH = msgkey[7]
PosI = msgkey[8]
PosJ = msgkey[9]

#Dekryptera, baklänges genom hjulen
for y in range(4):
  for x in range(29):
    if j[x] == enc[y]:
        valJ = (x-PosJ)%29
  for x in range(29):
    if i[x] == valJ:
        valI = (x-PosI)%29
  for x in range(29):
    if h[x] == valI:
      valH = (x-PosH)%29
  for x in range(29):
    if g[x] == valH:
       valG = (x-PosG)%29
  for x in range(29):
    if f[x] == valG:
      valF = (x-PosF)%29
  for x in range(29):
    if e[x] == valF:
      valE = (x-PosE)%29
  for x in range(29):
    if d[x] == valE:
      valD = (x-PosD)%29
  for x in range(29):
    if c[x] == valD:
      valC = (x-PosC)%29
  for x in range(29):
    if b[x] == valC:
      valB = (x-PosB)%29
  for x in range(29):
    if a[x] == valB:
      valA = (x-PosA)%29
      dec[y] = valA
  #Rotera hjulen efter pinkey    
  PosA = PosA + pinkey[0]
  PosB = PosB + pinkey[1]
  PosC = PosC + pinkey[2]
  PosD = PosD + pinkey[3]
  PosE = PosE + pinkey[4]
  PosF = PosF + pinkey[5]
  PosG = PosG + pinkey[6]
  PosH = PosH + pinkey[7]
  PosI = PosI + pinkey[8]
  PosJ = PosJ + pinkey[9]
#Skriv ut den dekrypterade texten
print("Dekrypterat: ",dec)
Skriv svar