Descifrar un texto cifrado de Vigenère


28

El cifrado Vigenère era un cifrado polialfabético simple que básicamente aplicaba uno de varios cifrados César, según una clave. Básicamente, las letras en la tecla indican qué alfabeto desplazado usar. Para ese fin había una herramienta simple, llamada el cuadrado de Vigenère:

ingrese la descripción de la imagen aquí

Aquí cada fila es un alfabeto separado, que comienza con la letra correspondiente de la clave. Las columnas se utilizan para determinar la letra cifrada. El descifrado funciona de la misma manera, solo viceversa.

Supongamos que queremos encriptar la cadena CODEGOLF. También necesitamos una llave. En este caso la clave será FOOBAR. Cuando la clave es más corta que el texto plano, la extendemos por repetición, por lo tanto, la clave real que utilizamos es FOOBARFO. Ahora buscamos la primera letra de la clave, que es Fencontrar el alfabeto. Comienza, quizás como era de esperar, con F. Ahora encontramos la columna con la primera letra del texto sin formato y la letra resultante es H. Para la segunda letra tenemos Ocomo letra clave y la letra de texto sin formato, lo que resulta en C. Continuando de esa manera finalmente llegamos HCRFGFQT.

Tarea

Su tarea ahora es descifrar mensajes, con una clave. Sin embargo, dado que hemos superado el siglo XVI y tenemos computadoras, al menos deberíamos admitir un alfabeto un poco más grande:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

La construcción de la plaza Vigenère sigue siendo muy parecida y el cifrado sigue funcionando de la misma manera. Es un poco ... difícil de manejar para dar aquí por completo.

Entrada

La entrada se proporciona en la entrada estándar como dos líneas de texto separadas, cada una terminada por un salto de línea. La primera línea contiene la clave, mientras que la segunda contiene el texto cifrado.

Salida

Una sola línea, que contiene el mensaje descifrado.

Condición ganadora

Dado que el cifrado a veces se considera un arma, el código debe ser breve para facilitar el contrabando. Cuanto más corto, mejor, ya que reduce la probabilidad de descubrimiento.

Entrada de muestra 1

Key
miQ2eEO

Salida de muestra 1

Message

Entrada de muestra 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Salida de muestra 2

ThisWorksEquallyWellWithNumbers123894576

Ha pasado una semana. La solución más corta actualmente ha sido aceptada. Para aquellos interesados, en nuestro concurso tuvimos las siguientes presentaciones y duraciones:

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

Y nuestras propias soluciones que no se clasificaron con las demás:

108 - Ruby
139 - PowerShell


Parece que esto puede ser útil para imprimir el cuadrado de Vigenère.
Erik the Outgolfer

Respuestas:


10

Golfscript - 48 caracteres

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

No hay trucos en este!


1 Fui a la cama pensando que debe haber una manera de conseguir esto a ~ 50, ahora veo que es posible, pero probablemente no habría conseguido en el corto plazo
gnibbler

8

Archivo .COM de 16 bits de MS-DOS - 87 bytes

Binario codificado en Base64 ( siguiendo este enlace para un decodificador )

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

Por lo general, usted mismo escribe un código fuente corto para jugar al golf. Aunque probablemente no sea imposible, de alguna manera lo dudo con esto.
Joey

@Joey: ¡Qué, nunca has codificado a mano las instrucciones del código de máquina! Justo lo que enseñan a los jóvenes en estos días! ;-)
Skizz

Skizz: lo hice. Sin embargo, no en Base64;) (tuvimos una clase hace unos años donde tuvimos que escribir programas para un Siemens 80C167 en ensamblador, y en los exámenes también los ensamblamos en código máquina. Pensé en desenterrar ese conocimiento para el ensamblador Quine tarea, pero no teníamos instalaciones de salida [al menos, variaron]).
Joey

@Joey: El Base64 es solo una conveniencia para los otros usuarios en este sitio, es fácil de decodificar y guardar como un archivo binario (el enlace en la respuesta tiene esa opción).
Skizz

Ah, lo siento. Pensé que habrías dado la longitud del Base64. Bueno, Chris una vez incluyó personajes arbitrarios en una solución y solo dio un hechizo además de su respuesta. Hice algo similar en el pronóstico del tiempo.
Joey

8

APL (45)

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

Explicación:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: genera el alfabeto (los números ( ⎕D) siguen letras ( ⎕A) siguen letras minúsculas ( ⎕UCS 96+⍳26, los valores unicode de 97 a 122).

  • 1-⍨⍞⍳⍨∆: lea una línea (la clave), encuentre la posición de cada carácter en el alfabeto y reste uno (las matrices están basadas en uno de forma predeterminada, por lo que desplazar esos valores directamente desplazaría demasiado el alfabeto).

  • (⍴⍙←⍞)⍴: lea otra línea (el mensaje) y repita los índices de la clave para que tenga la longitud del mensaje.
  • ⌽∘∆¨: rotar el alfabeto por los índices que pertenecen a la clave
  • ⍙⍳⍨¨: busque cada carácter en el mensaje en el alfabeto desplazado correspondiente
  • ∆[... ]: busque los índices dados en el alfabeto normal, dando los caracteres correspondientes.

6

Ruby - 132 127 122 109 100 caracteres

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

Use en *$<lugar de $<.to_ae incorpore la lambda para guardar otros pocos bytes. - Ventero hace 5 minutos
Joey

Gracias @Joey, saqué esa lambda para salvar personajes y de alguna manera extrañé que realmente costara más.
Nemo157

5

Python - 122 caracteres

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 caracteres

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

No cumple completamente con la especificación, ya que se define como un verbo en lugar de tomar datos, pero lo publico de todos modos con la intención de jugar con él en una fecha posterior.

Uso:

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

4

Perl, 95 caracteres

Perl 5.010, ejecuta con 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 caracteres

Probablemente no sea el mejor, pero bueno:

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, estaba a punto de publicar algo así. Puede asignar raw_input a una variable, más o menos 3 caracteres.
Juan

3

Golfscript - 65 caracteres

Todavía necesita jugar más al golf. Por ahora, T es el texto, K es la clave, L es la lista de letras

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 caracteres

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

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

Probablemente mucho más de lo que debe ser. Aún trato de entender a GS.

Aquí está la versión "no golfista" y comentada

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

No supera el puntaje VB.NET listado (pero me estoy acercando):

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

Uso:

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

Gracias a Joey por la informacion!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)Sería un candidato que puedo detectar. Además de probar si VBA comprende las terminaciones de línea LF. x=x & Z(g)Supongo que también se puede dejar al menos un espacio adentro .
Joey

Otra forma de escribir la línea: g=g+i*((Z(i)=d)-(Z(i)=c)) (porque Truees −1 en VB). Podría ser que funciona.
Joey

Gracias por los comentarios, @Joey.
Buscaré

2

C, 186

Un poco tarde pero ... (líneas interrumpidas para evitar la barra de desplazamiento 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]);}

Líneas no interrumpidas

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

Una discusión sobre el proceso de golf de este código se puede encontrar aquí: 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 caracteres

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

Por ejemplo:

    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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.