Déchiffrer un texte chiffré Vigenère


28

Le chiffrement Vigenère était un chiffrement polyalphabétique simple qui appliquait essentiellement l'un des chiffrements César, selon une clé. Fondamentalement, les lettres de la touche indiquent l'alphabet décalé à utiliser. À cette fin, il y avait un outil simple, appelé le carré Vigenère:

entrez la description de l'image ici

Ici, chaque ligne est un alphabet distinct, commençant par la lettre correspondante de la clé. Les colonnes sont ensuite utilisées pour déterminer la lettre chiffrée. Le déchiffrement fonctionne à peu près de la même manière, mais vice-versa.

Supposons que nous voulons chiffrer la chaîne CODEGOLF. Nous avons également besoin d'une clé. Dans ce cas, la clé doit être FOOBAR. Lorsque la clé est plus courte que le texte en clair, nous l'étendons par répétition, donc la clé réelle que nous utilisons est FOOBARFO. Nous recherchons maintenant la première lettre de la clé, qui est Fde trouver l'alphabet. Cela commence, peut-être sans surprise, par F. Maintenant, nous trouvons la colonne avec la première lettre du texte en clair et la lettre résultante est H. Pour la deuxième lettre, nous avons Ocomme lettre clé et la lettre de texte brut, résultant en C. En continuant ainsi, nous arrivons enfin HCRFGFQT.

Tâche

Votre tâche consiste maintenant à déchiffrer les messages, à l'aide d'une clé. Cependant, depuis que nous avons dépassé le XVIe siècle et que nous avons des ordinateurs, nous devrions au moins prendre en charge un alphabet légèrement plus grand:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

La construction de la place Vigenère est toujours à peu près la même et le chiffre fonctionne toujours de la même manière. C'est juste un peu ... difficile à donner ici en entier.

Contribution

L'entrée est donnée sur l'entrée standard sous la forme de deux lignes de texte distinctes, chacune terminée par un saut de ligne. La première ligne contient la clé tandis que la seconde contient le texte chiffré.

Sortie

Une seule ligne, contenant le message déchiffré.

Condition gagnante

Le cryptage étant parfois considéré comme une arme, le code doit être court pour faciliter la contrebande. Le plus court sera le mieux, car cela réduit la probabilité de découverte.

Exemple d'entrée 1

Key
miQ2eEO

Exemple de sortie 1

Message

Exemple d'entrée 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Exemple de sortie 2

ThisWorksEquallyWellWithNumbers123894576

Une semaine s'est écoulée. La solution actuellement la plus courte a été acceptée. Pour les personnes intéressées, dans notre concours, nous avions les soumissions et les longueurs suivantes:

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

Et nos propres solutions qui n'étaient pas classées avec les autres:

108 - Rubis
139 - PowerShell


Il semble que cela puisse être utile pour imprimer le carré Vigenère.
Erik the Outgolfer

Réponses:


10

Golfscript - 48 caractères

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

Pas de trucs dans celui-ci!


+1 Je me suis couché en pensant qu'il devait y avoir un moyen de ramener cela à ~ 50, maintenant je vois que c'est possible mais je ne l'aurais probablement pas réussi de si tôt
gnibbler

8

Fichier .COM MS-DOS 16 bits - 87 octets

Binaire encodé en Base64 (en suivant ce lien pour un décodeur )

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

Habituellement, vous écrivez vous-même un court code source pour jouer au golf. Bien que ce ne soit probablement pas impossible, j'en doute d'une manière ou d'une autre.
Joey

@Joey: Quoi, vous n'avez jamais reçu d'instructions de code machine encodées à la main! Qu'est-ce qu'ils enseignent aux jeunes de nos jours! ;-)
Skizz

Skizz: Oui. Pas en Base64, cependant;) (nous avions une classe il y a quelques années où nous devions écrire des programmes pour un Siemens 80C167 en assembleur - et dans les examens, les assembler également en code machine. J'ai pensé à creuser ces connaissances pour l'assembleur Quine task, mais nous n'avions pas d'installations de sortie [du moins, elles variaient]).
Joey

@Joey: Le Base64 est juste une commodité pour les autres utilisateurs de ce site, il est facile à décoder et à enregistrer en tant que fichier binaire (le lien dans la réponse a cette option).
Skizz

Ah, désolé. Je pensais que vous auriez donné la longueur de la Base64. Eh bien, Chris a inclus une fois des caractères arbitraires dans une solution et a juste donné un hexdump en plus de sa réponse. J'ai fait de même dans les prévisions météorologiques.
Joey

8

APL (45)

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

Explication:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: générer l'alphabet (les chiffres ( ⎕D) suivent les lettres ( ⎕A) suivent les lettres minuscules ( ⎕UCS 96+⍳26, les valeurs unicode de 97 à 122).

  • 1-⍨⍞⍳⍨∆: lire une ligne (la clé), trouver la position de chaque caractère dans l'alphabet, et soustraire un (les tableaux sont basés sur un par défaut, donc le décalage direct de ces valeurs déplacerait l'alphabet trop loin).

  • (⍴⍙←⍞)⍴: lire une autre ligne (le message), et répéter les index de la clé pour qu'elle ait la longueur du message.
  • ⌽∘∆¨: faire pivoter l'alphabet par les indices appartenant à la clé
  • ⍙⍳⍨¨: rechercher chaque caractère du message dans l'alphabet décalé correspondant
  • ∆[... ]: recherchez les indices donnés dans l'alphabet normal, en donnant les caractères correspondants.

6

Rubis - 132127122109100100 caractères

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

Utilisez *$<au lieu de $<.to_aet insérez le lambda pour enregistrer quelques octets supplémentaires. - Ventero Il y a 5 minutes
Joey

Merci @Joey, j'ai sorti cette lambda pour sauver des personnages et j'ai raté que ça coûte plus cher.
Nemo157

5

Python - 122 caractères

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 caractères

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

Ne répond pas complètement à la spécification car il est défini comme un verbe plutôt que de prendre une entrée, mais je le poste quand même avec l'intention de le manipuler à une date ultérieure.

Usage:

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

4

Perl, 95 caractères

Perl 5.010, exécuté avec 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 140 136 125 caractères

Probablement pas le meilleur, mais bon:

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, j'étais sur le point de publier quelque chose comme ça. Vous pouvez affecter raw_input à une variable, environ 3 caractères.
Juan

3

Golfscript - 65 caractères

Il faut encore jouer au golf plus. Pour l'instant, T est le texte, K est la clé, L est la liste des lettres

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 caractères

$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 caractères

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

Probablement beaucoup plus longtemps que nécessaire. J'essaie toujours de comprendre la GS.

Voici la version "non golfée" et commentée

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

Ne bat pas tout à fait le score VB.NET répertorié (mais je m'approche):

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

Usage:

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

Merci à Joey pour le conseil!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)serait un candidat que je peux repérer. En plus d'essayer de savoir si les terminaisons de ligne LF sont comprises par VBA. x=x & Z(g)J'imagine qu'au moins un espace pourrait être laissé de côté.
Joey

Une autre façon d'écrire la ligne: g=g+i*((Z(i)=d)-(Z(i)=c)) (car Trueest -1 en VB). Peut-être que cela fonctionne.
Joey

Merci pour la rétroaction, @Joey. Je chercherai d'autres améliorations et j'ajouterai cela.
Gaffi

2

C, 186

Un peu en retard mais .. (lignes brisées pour éviter la barre de défilement horizontale).

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

Lignes non interrompues

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

Une discussion sur le processus de golf de ce code peut être trouvée ici: 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 caractères

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

Par exemple:

    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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.