Odszyfruj tekst zaszyfrowany Vigenère


28

Szyfr vigenère'a był prosty szyfr polialfabetyczny że w zasadzie stosować jedną z kilku szyfrów Cezara, według klucza. Zasadniczo litery w klawiszach wskazują, którego przesuniętego alfabetu należy użyć. W tym celu było proste narzędzie, zwane kwadratem Vigenère:

wprowadź opis zdjęcia tutaj

Tutaj każdy wiersz to osobny alfabet, zaczynający się od odpowiedniej litery klucza. Kolumny służą następnie do ustalenia zaszyfrowanej litery. Deszyfrowanie działa w bardzo podobny sposób, tylko na odwrót.

Załóżmy, że chcemy zaszyfrować ciąg CODEGOLF. Potrzebujemy również klucza. W takim przypadku kluczem będzie FOOBAR. Kiedy klucz jest krótszy niż zwykły tekst, przedłużamy go przez powtórzenie, dlatego faktycznie używamy klucza FOOBARFO. Teraz patrzymy na pierwszą literę klucza, którą jest Fznalezienie alfabetu. Zaczyna się, być może nic dziwnego, od F. Teraz znajdujemy kolumnę z pierwszą literą tekstu jawnego, a wynikową literą jest H. W przypadku drugiej litery mamy literę Okluczową i literę zwykłego tekstu, w wyniku czego C. Kontynuując w ten sposób, w końcu dostajemy HCRFGFQT.

Zadanie

Twoim zadaniem jest teraz odszyfrowanie wiadomości przy użyciu klucza. Ponieważ jednak wyrosliśmy z XVI wieku i dysponujemy komputerami, powinniśmy przynajmniej obsługiwać nieco większy alfabet:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Budowa placu Vigenère jest nadal bardzo podobna, a szyfr nadal działa w ten sam sposób. To tylko trochę ... nieporęczne dać tutaj w całości.

Wkład

Dane wejściowe są podawane na standardowym wejściu jako dwa oddzielne wiersze tekstu, z których każdy kończy się podziałem wiersza. Pierwszy wiersz zawiera klucz, a drugi tekst zaszyfrowany.

Wydajność

Pojedynczy wiersz zawierający odszyfrowaną wiadomość.

Warunki wygranej

Ponieważ szyfrowanie jest czasem uważane za broń, kod powinien być krótki, aby ułatwić łatwy przemyt. Im krótszy, tym lepiej, ponieważ zmniejsza prawdopodobieństwo odkrycia.

Przykładowe dane wejściowe 1

Key
miQ2eEO

Próbka wyjściowa 1

Message

Przykładowe wejście 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Przykładowe wyjście 2

ThisWorksEquallyWellWithNumbers123894576

Minął tydzień. Obecnie najkrótsze rozwiązanie zostało zaakceptowane. Dla zainteresowanych w naszym konkursie mieliśmy następujące zgłoszenia i długości:

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

A nasze własne rozwiązania, które nie zostały ocenione w rankingu wśród innych:

108 - Ruby
139 - PowerShell


Wydaje się, że może to być przydatne do wydrukowania kwadratu Vigenère.
Erik the Outgolfer,

Odpowiedzi:


10

Golfscript - 48 znaków

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

Żadnych sztuczek w tym!


+1 Poszedłem spać, myśląc, że musi być sposób na obniżenie tego do ~ 50, teraz widzę, że to możliwe, ale prawdopodobnie nie poradziłbym sobie z tym wkrótce
gnibbler

8

MS-DOS 16-bitowy plik .COM - 87 bajtów

Kod binarny Base64 ( po tym linku do dekodera )

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

Zwykle sam piszesz krótki kod źródłowy do gry w golfa. Chociaż prawdopodobnie nie jest to niemożliwe, jakoś w to wątpię.
Joey,

@Joey: Co, nigdy nie podałeś instrukcji kodowania maszynowego! Czego uczą obecnie młodzież! ;-)
Skizz

Skizz: Tak zrobiłem. Ale nie w Base64;) (kilka lat temu mieliśmy klasę, w której musieliśmy pisać programy dla asemblera dla Siemens 80C167 - a na egzaminach również montować je w kodzie maszynowym. Myślałem o wydobyciu tej wiedzy dla asemblera Zadanie Quine, ale nie mieliśmy urządzeń wyjściowych [przynajmniej były różne]).
Joey,

@Joey: Base64 to tylko wygoda dla innych użytkowników tej witryny, można go łatwo zdekodować i zapisać jako plik binarny (link w odpowiedzi ma tę opcję).
Skizz

Ach, przepraszam. Myślałem, że podasz długość Base64. Cóż, Chris kiedyś umieścił dowolne postacie w rozwiązaniu i po prostu dał zrzut heksowy oprócz swojej odpowiedzi. Zrobiłem podobnie w prognozie pogody.
Joey,

8

APL (45)

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

Wyjaśnienie:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: generuj alfabet (cyfry ( ⎕D) podążaj za literami ( ⎕A) podążaj za małymi literami ( ⎕UCS 96+⍳26wartości Unicode od 97 do 122).

  • 1-⍨⍞⍳⍨∆: przeczytaj wiersz (klawisz), znajdź pozycję każdego znaku w alfabecie i odejmij jeden (tablice domyślnie są oparte na jednym, więc przesunięcie o te wartości bezpośrednio spowoduje przesunięcie alfabetu o jeden za daleko).

  • (⍴⍙←⍞)⍴: przeczytaj inny wiersz (wiadomość) i powtórz indeksy klucza, aby miał długość wiadomości.
  • ⌽∘∆¨: obracaj alfabet według indeksów należących do klucza
  • ⍙⍳⍨¨: wyszukaj każdy znak w wiadomości w odpowiednim przesuniętym alfabecie
  • ∆[... ]: wyszukaj podane indeksy w normalnym alfabecie, podając odpowiednie znaki.

6

Rubin - 132 127 122 109 100 znaków

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)])]}

Użyj *$<zamiast $<.to_ai wstaw lambda, aby zaoszczędzić kolejne kilka bajtów. - Ventero 5 minut temu
Joey

Dzięki @Joey, wyciągnąłem tę lambdę, aby uratować postacie i jakoś tęskniłem, że faktycznie kosztowała więcej.
Nemo157

5

Python - 122 znaki

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 znaków

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

Nie jest w pełni zgodny ze specyfikacją, ponieważ jest zdefiniowany jako czasownik, a nie przyjmowanie danych wejściowych, ale i tak publikuję go z zamiarem bycia z nim w późniejszym czasie.

Stosowanie:

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

4

Perl, 95 znaków

Perl 5.010, uruchamiany z 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 znaków

Prawdopodobnie nie najlepszy, ale hej:

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, miałem właśnie zamieścić coś takiego. Możesz przypisać raw_input do zmiennej, około 3 znaków.
Juan

3

Golfscript - 65 znaków

Nadal trzeba grać w golfa więcej. Na razie T to tekst, K to klucz, L to lista liter

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 znaków

$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 znaki

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

Prawdopodobnie znacznie dłużej niż trzeba. Wciąż próbuję obejść GS.

Oto wersja „nieposkromiona” i skomentowana

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

Nie do końca pobił wymieniony wynik VB.NET (ale zbliżam się):

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

Stosowanie:

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

Dzięki Joey za wskazówkę!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)byłby jednym kandydatem, którego mogę dostrzec. Oprócz sprawdzania, czy zakończenia linii LF są rozumiane przez VBA. x=x & Z(g)Wydaje mi się, że można pominąć przynajmniej jedno miejsce .
Joey,

Innym sposobem pisania linii: g=g+i*((Z(i)=d)-(Z(i)=c)) (ponieważ Truejest −1 w VB). Może być tak, że to działa.
Joey,

Dzięki za opinie, @Joey. Poszukam innych ulepszeń i dodam to.
Gaffi

2

C, 186

Trochę późno, ale ... (linie przerywane, aby uniknąć poziomego paska przewijania).

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]);}

Nieprzerwane linie

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]);}

Dyskusję na temat gry w golfa w tym kodzie można znaleźć tutaj: 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 (169)

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 znaków

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

Na przykład:

    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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.