Entschlüsseln Sie einen Vigenère-Geheimtext


28

Die Vigenère-Chiffre war eine einfache polyalphabetische Chiffre, bei der im Grunde genommen einer von mehreren Cäsar-Chiffren gemäß einem Schlüssel angewendet wurde. Grundsätzlich geben die Buchstaben in der Taste an, welches verschobene Alphabet verwendet werden soll. Zu diesem Zweck gab es ein einfaches Werkzeug namens Vigenère-Platz:

Bildbeschreibung hier eingeben

Hier ist jede Zeile ein separates Alphabet, beginnend mit dem entsprechenden Buchstaben der Taste. Die Spalten werden dann verwendet, um den verschlüsselten Buchstaben zu bestimmen. Die Entschlüsselung funktioniert sehr ähnlich, nur umgekehrt.

Angenommen, wir möchten die Zeichenfolge verschlüsseln CODEGOLF. Wir brauchen auch einen Schlüssel. In diesem Fall ist der Schlüssel FOOBAR. Wenn der Schlüssel kürzer als der Klartext ist, erweitern wir ihn durch Wiederholung, daher ist der tatsächliche Schlüssel, den wir verwenden, der FOOBARFO. Wir schlagen nun den ersten Buchstaben der Taste Fnach, um das Alphabet zu finden. Es beginnt, vielleicht nicht überraschend, mit F. Nun finden wir die Spalte mit dem ersten Buchstaben des Klartextes und dem resultierenden Buchstaben ist H. Für den zweiten Buchstaben haben wir Oals Schlüssel den Buchstaben und als Klartext den Buchstaben, woraus sich ergibt C. Wenn wir so weitermachen, haben wir es endlich geschafft HCRFGFQT.

Aufgabe

Ihre Aufgabe ist es nun, Nachrichten mit einem Schlüssel zu entschlüsseln. Da wir jedoch aus dem 16. Jahrhundert herausgewachsen sind und Computer haben, sollten wir zumindest ein etwas größeres Alphabet unterstützen:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Der Bau des Vigenère-Platzes ist immer noch sehr ähnlich und die Chiffre funktioniert immer noch auf die gleiche Weise. Es ist nur ein bisschen ... unhandlich, hier in vollem Umfang zu geben.

Eingang

Die Eingabe erfolgt in der Standardeingabe als zwei separate Textzeilen, die jeweils durch einen Zeilenumbruch abgeschlossen werden. Die erste Zeile enthält den Schlüssel, während die zweite den Chiffretext enthält.

Ausgabe

Eine einzelne Zeile, die die entschlüsselte Nachricht enthält.

Gewinnbedingung

Da die Verschlüsselung manchmal als Waffe angesehen wird, sollte der Code kurz sein, um das Schmuggeln zu erleichtern. Je kürzer desto besser, da die Wahrscheinlichkeit einer Entdeckung verringert wird.

Probeneingabe 1

Key
miQ2eEO

Beispielausgabe 1

Message

Probeneingabe 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Beispielausgabe 2

ThisWorksEquallyWellWithNumbers123894576

Eine Woche ist vergangen. Die aktuell kürzeste Lösung wurde angenommen. Für die Interessenten hatten wir bei unserem Wettbewerb folgende Einreichungen und Längen:

130 - Python
146 - Haskell
195 - C
197 - C
267 - VB.NET

Und unsere eigenen Lösungen, die nicht mit den anderen verglichen wurden:

108 - Ruby
139 - PowerShell


Es scheint, dass dies nützlich sein kann, um das Vigenère-Quadrat zu drucken.
Erik der Outgolfer

Antworten:


10

Golfscript - 48 Zeichen

n%~.,@*\{\(123,97>91,65>+58,48>+:|?@|?\-|=}%\0<+

Keine Tricks in diesem!


+1 Ich ging ins Bett und dachte, es müsste eine Möglichkeit geben, dies auf ~ 50 zu bringen. Jetzt sehe ich, dass es möglich ist, aber ich hätte es wahrscheinlich nicht so schnell geschafft
Gnibbler

8

MS-DOS 16-Bit-COM-Datei - 87 Byte

Base64-codierte Binärdatei ( folgen Sie diesem Link für einen Decoder )

v1cBi8/oQACJ/ovv6DkAi9msitAqF3MDgMI+gMJhgPp6dguA6jqA+lp2A4DqK80hO/d0IkM563TW69YsYXMIBCB9AgQrBBqqtAHNITwNdev+xLIKzSHD

Normalerweise schreiben Sie selbst einen kurzen Quellcode zum Golfen. Obwohl es wahrscheinlich nicht unmöglich ist, bezweifle ich es irgendwie damit.
Joey

@ Joey: Was, Sie haben noch nie codierte Maschinencode-Anweisungen übergeben! Was bringen sie den Jugendlichen heutzutage bei? ;-)
Skizz

Skizz: Das habe ich getan. Allerdings nicht in Base64;) (wir hatten vor ein paar Jahren eine Klasse, in der wir Programme für einen Siemens 80C167 in Assembler schreiben mussten - und in den Prüfungen auch in Maschinencode. Ich dachte darüber nach, dieses Wissen für den Assembler herauszufinden Quine Aufgabe, aber wir hatten keine Ausgabemöglichkeiten (zumindest variierten sie).
Joey

@Joey: Der Base64 ist nur eine Annehmlichkeit für die anderen Benutzer auf dieser Site. Er kann einfach dekodiert und als Binärdatei gespeichert werden (der Link in der Antwort enthält diese Option).
Skizz

Aah, Entschuldigung. Ich dachte, Sie hätten die Länge des Base64 angegeben. Nun, Chris hat einmal beliebige Zeichen in eine Lösung aufgenommen und neben seiner Antwort nur einen Hexdump ausgegeben. Ähnliches habe ich in der Wettervorhersage gemacht.
Joey

8

APL (45)

∆[⍙⍳⍨¨⌽∘∆¨(⍴⍙←⍞)⍴1-⍨⍞⍳⍨∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26]

Erläuterung:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: Erzeugt das Alphabet (Zahlen ( ⎕D) folgen Buchstaben ( ⎕A) folgen Kleinbuchstaben ( ⎕UCS 96+⍳26, die Unicode-Werte von 97 bis 122).

  • 1-⍨⍞⍳⍨∆: Lies eine Zeile (die Taste), finde die Position jedes Buchstabens im Alphabet und subtrahiere eine (Arrays sind standardmäßig eins-basiert, also würde eine direkte Verschiebung um diese Werte das Alphabet zu weit verschieben).

  • (⍴⍙←⍞)⍴: Lesen Sie eine weitere Zeile (die Nachricht) und wiederholen Sie die Indexe des Schlüssels, damit er die Länge der Nachricht hat.
  • ⌽∘∆¨: drehen Sie das Alphabet um die zum Schlüssel gehörenden Indizes
  • ⍙⍳⍨¨: Jedes Zeichen in der Nachricht im entsprechenden verschobenen Alphabet nachschlagen
  • ∆[... ]: Nachschlagen der angegebenen Indizes im normalen Alphabet unter Angabe der entsprechenden Zeichen.

6

Ruby - 132 127 122 109 100 Zeichen

a,b=*$<
c=*?a..?z,*?A..?Z,*?0..?9
(b.size-1).times{|i|$><<c[c.index(b[i])-c.index(a[i%(a.size-1)])]}

Verwenden Sie *$<anstelle von $<.to_aund inline das Lambda, um weitere wenige Bytes zu sparen. - Ventero vor 5 Minuten
Joey

Danke @Joey, ich habe das Lambda rausgezogen, um Charaktere zu retten und irgendwie verpasst, dass es tatsächlich mehr kostet.
Nemo157,

5

Python - 122 Zeichen

from string import*
L=letters+digits
R=raw_input
K,T=R(),R()
F=L.find
print"".join(L[F(i)-F(j)]for i,j in zip(T,K*len(T)))

5

J, 65 Zeichen

v=:4 : 'a{~x(62|[:-/"1 a i.[,.#@[$])y[a=.a.{~62{.;97 65 48+/i.26'

Erfüllt die Spezifikation nicht vollständig, da sie als Verb definiert ist, anstatt Eingaben zu machen, aber ich poste sie trotzdem mit der Absicht, zu einem späteren Zeitpunkt damit zu experimentieren.

Verwendung:

   'miQ2eEO' v 'Key'
Message
   'CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu' v 'ThisIsAKey'
ThisWorksEquallyWellWithNumbers123894576

4

Perl, 95 Zeichen

Perl 5.010, lauffähig mit perl -E:

%a=map{$_,$n++}@a=(a..z,A..Z,0..9);@k=<>=~/./g;
$_=<>;s/./$a[($a{$&}-$a{$k[$i++%@k]})%62]/ge;say

3

Python - 144 143 140 136 125 Zeichen

Wahrscheinlich nicht die beste, aber hey:

from string import*
l=letters+digits
r=l.find
q=raw_input
k=q()
print"".join(l[(r(j)-r(k[i%len(k)]))%62]for i,j in enumerate(q()))

Huh, ich wollte gerade so etwas posten. Sie können raw_input einer Variablen mit 3 oder mehr Zeichen zuweisen.
Juan

3

Golfscript - 65 Zeichen

Muss noch mehr golfen. Im Moment ist T der Text, K ist der Schlüssel, L ist die Liste der Buchstaben

n%):T,\~*:K;''26,{97+}%+.{32^}%10,{48+}%++:L;T{L\?K(L\?\:K;-L\=}%

3

K 81, 61

k:0:0;,/$(m!+(`$'m)!+{(1_x),1#x}\m:,/.Q`a`A`n)[(#v)#k]?'v:0:0

.

k)k:0:0;,/$(m!+(`$'m)!+{(1_x),1#x}\m:,/.Q`a`A`n)[(#v)#k]?'v:0:0
ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu
"ThisWorksEquallyWellWithNumbers123894576"

2

Perl, 115 Zeichen

$a=join'',@A=(a..z,A..Z,0..9);$_=<>;chop;@K=split//;$_=<>;s/./$A[(index($a,$&)-index($a,$K[$-[0]%@K]))%@A]/ge;print

2

Golfscript - 92 Zeichen

n%~\.,:l;{0\{1$+\)\}%\;}:&;26'a'*&26'A'*&+10'0'*&+\@.,,{.l%3$=4$?\2$=4$?\- 62%3$\>1<}%\;\;\;

Wahrscheinlich viel länger als nötig. Ich versuche immer noch, meinen Kopf um GS zu drehen.

Hier ist die "ungolfed" und kommentierte Version

n%~\.,:l;
{0\{1$+\)\}%\;}:&; # This would be sortof an equivalent for range applied to strings
26'a'*&26'A'*&+10'0'*&+\@., # This mess generates the dictionary string,
# l = len(key)
# 0 dictionary (letters + digits)
# 1 key
# 2 text
{
    # 3 index
    .   #+1 Duplicate the index

    # Find the index of the key letter
    l%  #+1 Indice modulo key
    3$  #+2 Duplicate the key
    =   #+1 Get the key letter
    4$? #+1 Search the letters index

    # Find the index of the text letter
    \   #+1 Get the index
    2$  #+2 Get the text
    =   #+1 Get the text letter
    4$? #+0 Search the letters index

    # 3 key index
    # 4 letter index

    \-   #+1 get the index of the new letter

    62% #+1 wrap the index around the dictionary

    3$ #+2 Get the dictionary

    \> #+1 remove the first part of the dict around the target letter

    1< #+1 remove everythin after 
}%
\;
\;
\;

2

VBA, 288

Übertrifft die aufgeführte VB.NET-Wertung nicht ganz (aber ich komme näher):

Sub h(k,s)
v=Chr(0)
Z=Split(StrConv("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",64),v)
a=Split(StrConv(s,64),v):b=Split(StrConv(k,64),v)
For l=0 To Len(s)-1
j=l Mod Len(k)
g=0
For i=0 To 62:g=g+i*((Z(i)=b(j))-(Z(i)=a(l))):Next
x=x &Z(IIf(g<0,g+62,g))
Next
s=x
End Sub

Verwendung:

Sub test()
k = "ThisIsAKey"
s = "CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu"
h k, s
MsgBox s
End Sub

Danke an Joey für den Tipp!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)wäre ein Kandidat, den ich erkennen kann. Ebenso wie das Ausprobieren, ob LF-Leitungsenden von VBA verstanden werden. Mindestens ein Leerzeichen x=x & Z(g)könnte auch weggelassen werden, denke ich.
Joey

Eine andere Art, die Zeile zu schreiben: g=g+i*((Z(i)=d)-(Z(i)=c)) (weil True−1 in VB ist). Könnte sein, dass es funktioniert.
Joey

Danke für das Feedback, @Joey. Ich werde nach weiteren Verbesserungen suchen und diese hinzufügen.
Gaffi

2

C 186

Ein bisschen spät, aber ... (Zeilen werden unterbrochen, um horizontale Bildlaufleiste zu vermeiden).

char a[99],*s,*t;k,j;main(int m,char**v)
{for(;j<26;++j)a[j]=32|(a[j+26]=65+j),
a[52+j]=48+j;while(*v[2])
putchar(a[s=strchr(a,v[1][k++%strlen(v[1])])
,t=strchr(a,*v[2]++),s>t?t-s+62:t-s]);}

Nicht unterbrochene Linien

char a[99],*s,*t;k,j;main(int m,char**v){for(;j<26;++j)a[j]=32|(a[j+26]=65+j),a[52+j]=48+j;while(*v[2])putchar(a[s=strchr(a,v[1][k++%strlen(v[1])]),t=strchr(a,*v[2]++),s>t?t-s+62:t-s]);}

Eine Diskussion über den Vorgang des Golfspielens dieses Codes finden Sie hier: http://prob-slv.blogspot.com/2013/04/code-golf.html


2

JavaScript 248

var v= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
function d(k,c){var a,b,o,x
a=k.charAt(0)
x=v.indexOf(a)
b=v.substr(x)+v.substring(0,x)
o= v.charAt(b.indexOf(c.charAt(0)))
k=k.substr(1)+a
c=c.substr(1)
return (c)?o+d(k,c):o}

1

Haskell

import List
main=do c<-y;t<-y;putStrLn$map((k!!).(`mod`62))$zipWith(-)(g t)(cycle$g c)
k=['a'..'z']++['A'..'Z']++['0'..'9']
y=getLine
f(Just x)=x
g=map$f.(`elemIndex`k)

1

J: 91 Zeichen

[:{&{.&t({&t"0&(({.t=.1|.^:(i.62)a.{~(97+i.26),(65+i.26),48+i.10)&i.)"0@:$~#)|:@(i."1.,"0)]

Beispielsweise:

    g=:[:{&{.&t({&t"0&(({.t=.1|.^:(i.62)a.{~(97+i.26),(65+i.26),48+i.10)&i.)"0@:$~#)|:@(i."1.,"0)]
    'ThisIsAKey' g 'CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu'
ThisWorksEquallyWellWithNumbers123894576
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.