Menguraikan sandi Vigenère


28

The Vigenere cipher adalah cipher polyalphabetic sederhana yang pada dasarnya diterapkan salah satu dari beberapa cipher Caesar, menurut kunci. Pada dasarnya huruf-huruf pada tombol menunjukkan alfabet yang bergeser untuk digunakan. Untuk itu ada alat sederhana, yang disebut kotak Vigenère:

masukkan deskripsi gambar di sini

Di sini setiap baris adalah alfabet terpisah, dimulai dengan huruf yang sesuai dengan kunci. Kolom kemudian digunakan untuk menentukan huruf ciphered. Dekripsi bekerja dengan cara yang hampir sama, hanya sebaliknya.

Misalkan kita ingin mengenkripsi string CODEGOLF. Kami juga membutuhkan kunci. Dalam hal ini kuncinya adalah FOOBAR. Ketika kunci lebih pendek dari plaintext kita memperpanjangnya dengan pengulangan, oleh karena itu kunci sebenarnya yang kita gunakan adalah FOOBARFO. Kami sekarang mencari huruf pertama dari kunci, yaitu Funtuk menemukan alfabet. Itu dimulai, mungkin tidak mengejutkan, dengan F. Sekarang kita temukan kolom dengan huruf pertama dari plaintext dan huruf yang dihasilkan adalah H. Untuk huruf kedua kita miliki Osebagai surat kunci dan surat teks biasa, menghasilkan C. Terus seperti itu akhirnya kita dapatkan HCRFGFQT.

Tugas

Tugas Anda sekarang adalah menguraikan pesan, diberi kunci. Namun, karena kita telah melampaui abad ke-16 dan memiliki komputer, setidaknya kita harus mendukung alfabet yang sedikit lebih besar:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Konstruksi alun-alun Vigenère masih sangat sama dan sandi masih bekerja dengan cara yang sama. Hanya sedikit ... sulit untuk memberi di sini secara penuh.

Memasukkan

Input diberikan pada input standar sebagai dua baris teks yang terpisah, masing-masing diakhiri oleh satu baris. Baris pertama berisi kunci sementara yang kedua berisi ciphertext.

Keluaran

Satu baris, berisi pesan yang diuraikan.

Kondisi menang

Karena enkripsi kadang-kadang dianggap sebagai senjata, kodenya harus pendek untuk memudahkan penyelundupan. Semakin pendek semakin baik, karena mengurangi kemungkinan penemuan.

Masukan sampel 1

Key
miQ2eEO

Output sampel 1

Message

Masukan sampel 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Output sampel 2

ThisWorksEquallyWellWithNumbers123894576

Seminggu telah berlalu. Solusi terpendek saat ini telah diterima. Bagi mereka yang tertarik, dalam kontes kami kami memiliki kiriman dan panjang berikut:

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

Dan solusi kami sendiri yang tidak diberi peringkat dengan yang lain:

108 - Ruby
139 - PowerShell


Tampaknya ini berguna untuk mencetak kotak Vigenère.
Erik the Outgolfer

Jawaban:


10

Golfscript - 48 karakter

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

Tidak ada trik dalam hal ini!


+1 Saya pergi ke tempat tidur berpikir pasti ada cara untuk menurunkan ini ke ~ 50, sekarang saya melihat itu mungkin tapi saya mungkin tidak akan berhasil dalam waktu dekat
gnibbler

8

File .COM MS-DOS 16bit - 87 byte

Base64 encoded binary ( mengikuti tautan ini untuk decoder )

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

Biasanya Anda menulis sendiri kode sumber pendek untuk bermain golf. Meskipun mungkin bukan tidak mungkin, saya entah bagaimana meragukannya dengan ini.
Joey

@ Joey: Apa, Anda tidak pernah menyerahkan instruksi kode mesin yang dikodekan! Apa yang mereka ajarkan kepada anak-anak muda hari ini! ;-)
Skizz

Skizz: Ya. Namun tidak di Base64;) (kami memiliki kelas beberapa tahun yang lalu di mana kami harus menulis program untuk assembler Siemens 80C167 - dan dalam ujian juga merakitnya menjadi kode mesin. Saya berpikir untuk menggali pengetahuan itu untuk Assembler Tugas quine, tetapi kami tidak memiliki fasilitas output [setidaknya, mereka bervariasi]).
Joey

@ Joey: Base64 hanya kenyamanan bagi pengguna lain di situs ini, mudah untuk memecahkan kode dan menyimpannya sebagai file biner (tautan dalam jawaban memiliki opsi itu).
Skizz

Aah, maaf. Saya pikir Anda akan memberikan panjang Base64. Yah, Chris pernah memasukkan karakter sewenang-wenang ke dalam solusi dan hanya memberikan hexdump selain jawabannya. Saya melakukan hal yang sama dalam ramalan cuaca.
Joey

8

APL (45)

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

Penjelasan:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: menghasilkan alfabet (angka ( ⎕D) ikuti huruf ( ⎕A) ikuti huruf kecil ( ⎕UCS 96+⍳26, nilai unicode dari 97 hingga 122).

  • 1-⍨⍞⍳⍨∆: baca baris (tombol), cari posisi masing-masing karakter dalam alfabet, dan kurangi satu (array secara default berbasis satu, jadi dengan menggeser nilai-nilai itu secara langsung akan menggeser alfabet satu terlalu jauh).

  • (⍴⍙←⍞)⍴: baca baris lain (pesan), dan ulangi indeks kunci sehingga memiliki panjang pesan.
  • ⌽∘∆¨: putar alfabet dengan indeks yang dimiliki kunci
  • ⍙⍳⍨¨: cari setiap karakter dalam pesan dalam alfabet bergeser yang sesuai
  • ∆[... ]: cari indeks yang diberikan dalam alfabet normal, berikan karakter yang sesuai.

6

Ruby - 132 127 122 122 109 100 karakter

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

Gunakan *$<alih-alih $<.to_adan sebaris lambda untuk menyimpan beberapa byte lagi. - Ventero 5 mnt yang lalu
Joey

Terima kasih @ Joey, saya mengeluarkan lambda untuk menyimpan karakter dan entah bagaimana melewatkan bahwa itu sebenarnya lebih mahal.
Nemo157

5

Python - 122 karakter

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 karakter

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

Tidak sepenuhnya memenuhi spesifikasi karena itu didefinisikan sebagai kata kerja daripada mengambil input, tapi saya tetap mempostingnya dengan maksud mengutak-atiknya di kemudian hari.

Pemakaian:

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

4

Perl, 95 karakter

Perl 5.010, jalankan dengan 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 karakter

Mungkin bukan yang terbaik, tapi hei:

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, aku baru akan memposting sesuatu seperti itu. Anda dapat menetapkan raw_input ke variabel, 3 atau lebih karakter.
Juan

3

Golfscript - 65 karakter

Masih perlu bermain golf lebih banyak. Untuk saat ini, T adalah teks, K adalah Kunci, L adalah daftar huruf

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 karakter

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

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

Mungkin lebih lama dari yang seharusnya. Masih mencoba untuk membuat kepala saya sekitar GS.

Inilah versi yang "tidak bertali" dan berkomentar

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

Tidak cukup mengalahkan skor VB.NET yang terdaftar (tapi saya semakin dekat):

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

Pemakaian:

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

Terima kasih kepada Joey untuk tipnya!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)akan menjadi salah satu kandidat yang bisa saya temukan. Serta mencoba apakah akhir jalur LF dipahami oleh VBA. Setidaknya satu ruang di x=x & Z(g)bisa ditinggalkan juga, kurasa.
Joey

Cara lain untuk menulis baris: g=g+i*((Z(i)=d)-(Z(i)=c)) (karena True−1 dalam VB). Bisa jadi itu berhasil.
Joey

Terima kasih atas umpan baliknya, @ Joey. Saya akan mencari peningkatan lainnya dan menambahkannya.
Gaffi

2

C, 186

Agak terlambat tapi .. (garis putus-putus untuk menghindari scrollbar horizontal).

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

Garis tidak terputus

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

Diskusi tentang proses bermain golf kode ini dapat ditemukan di sini: 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 karakter

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

Sebagai contoh:

    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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.