Vigenère 암호문 해독


28

Vigenère 암호는 기본적으로 키에 따라 여러 시저 암호 중 하나를인가하는 간단한 다중 문자 암호이다. 기본적으로 키의 문자는 사용할 시프트 된 알파벳을 나타냅니다. 이를 위해 Vigenère 광장 이라는 간단한 도구가있었습니다 .

여기에 이미지 설명을 입력하십시오

여기서 각 행은 키의 해당 문자로 시작하는 별도의 알파벳입니다. 그런 다음 열은 암호 문자를 결정하는 데 사용됩니다. 암호 해독은 거의 같은 방식으로 작동하며 그 반대의 경우도 마찬가지입니다.

문자열을 암호화하려고한다고 가정하자 CODEGOLF. 우리는 또한 열쇠가 필요합니다. 이 경우 키는이어야한다 FOOBAR. 키가 평문보다 짧은 경우 반복하여 확장하므로 실제 사용하는 키는입니다 FOOBARFO. 이제 F알파벳을 찾는 키의 첫 글자 를 찾습니다. 아마 의심 할 여지없이로 시작합니다 F. 이제 우리는 평문의 첫 글자가있는 열을 찾고 결과 글자는 H입니다. 두 번째 문자는 O키 문자와 일반 텍스트 문자로 표시됩니다 C. 그런 식으로 계속 우리는 마침내 얻는다 HCRFGFQT.

태스크

당신의 임무는 이제 열쇠가 주어진 메시지를 해독하는 것입니다. 그러나 우리는 16 세기를 넘어서서 컴퓨터를 가지고 있기 때문에 최소한 약간 더 큰 알파벳을 지원해야합니다

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Vigenère 광장의 구성은 여전히 ​​매우 동일하며 암호는 여전히 똑같은 방식으로 작동합니다. 여기에 전체를 제공하는 것은 조금 까다 롭습니다.

입력

입력은 표준 입력에서 두 개의 개별 텍스트 줄로 제공되며 각각 줄 바꿈으로 종료됩니다. 첫 번째 줄에는 키가 있고 두 번째 줄에는 암호문이 있습니다.

산출

해독 된 메시지를 포함하는 단일 행.

승리 조건

암호화는 때때로 무기로 간주되기 때문에 밀수를 쉽게하기 위해 코드가 짧아야합니다. 발견 가능성을 줄이므로 짧을수록 좋습니다.

샘플 입력 1

Key
miQ2eEO

샘플 출력 1

Message

샘플 입력 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

샘플 출력 2

ThisWorksEquallyWellWithNumbers123894576

일주일이 지났습니다. 현재 가장 짧은 솔루션이 승인되었습니다. 컨테스트에 관심이있는 분들을 위해 다음과 같은 제출 및 길이가있었습니다.

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

그리고 다른 솔루션과 비교되지 않은 자체 솔루션 :

108 – Ruby
139 – PowerShell


것 같습니다 Vigenère 광장을 인쇄하는 것이 유용 할 수 있습니다.
Outgolfer Erik

답변:


10

골프 스크립트-48 자

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

이 트릭은 없습니다!


+1 나는 이것을 ~ 50까지 낮추는 방법이 있어야한다고 생각했다. 이제는 가능하지만 곧 관리하지는 못할 것이다.
gnibbler

8

MS-DOS 16 비트 .COM 파일-87 바이트

Base64로 인코딩 된 이진 ( 디코더의 경우이 링크 다음 )

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

일반적으로 골프를 위해 짧은 소스 코드를 직접 작성하십시오. 아마도 불가능하지는 않지만, 어떻게 든 의심합니다.
Joey

@Joey : 뭐, 당신은 인코딩 된 기계 코드 명령을 손으로 한 적이 없습니다! 요즘 젊은이들에게 무엇을 가르치나요? ;-)
Skizz 2019

Skizz : 했어요. 그러나 Base64에는 없습니다. Quine 과제이지만 출력 시설은 없었습니다 (적어도 다양 함).
Joey

@Joey : Base64는이 사이트의 다른 사용자에게 편의를 제공하며 바이너리 파일로 쉽게 디코딩하고 저장할 수 있습니다 (답변의 링크에는 해당 옵션이 있음).
Skizz

아 죄송합니다. 나는 당신이 Base64의 길이를 줄 것이라고 생각했습니다. 글쎄, Chris는 한 번에 임의의 문자를 솔루션에 포함 시켰고 그의 대답 외에 hexdump를 제공했습니다. 일기 예보에서도 비슷했습니다.
Joey

8

APL (45)

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

설명:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: 알파벳 (숫자 ( ⎕D) 뒤에 오는 문자 ( ⎕A) 뒤에 소문자 ( ⎕UCS 96+⍳26, 97에서 122까지의 유니 코드 값)을 생성합니다.

  • 1-⍨⍞⍳⍨∆: 한 줄 (키)을 읽고 알파벳에서 각 문자의 위치를 ​​찾고 하나를 뺍니다 (배열은 기본적으로 하나를 기반으로하므로 해당 값으로 직접 이동하면 알파벳이 너무 멀리 이동합니다).

  • (⍴⍙←⍞)⍴: 다른 줄 (메시지)을 읽고 메시지의 길이를 갖도록 키의 색인을 반복하십시오.
  • ⌽∘∆¨: 키에 속하는 인덱스로 알파벳을 회전
  • ⍙⍳⍨¨: 메시지에서 각 문자를 해당하는 알파벳으로 조회
  • ∆[... ]: 주어진 문자를 일반 알파벳으로 찾아 해당 문자를 제공합니다.

6

루비 - 132 127 122 109 100 자

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

람다 *$<대신 사용 $<.to_a하고 인라인하여 다른 몇 바이트를 저장하십시오. – Ventero 5 분 전
Joey

@Joey에게 감사드립니다. 문자를 저장하기 위해 람다를 꺼내고 실제로 더 많은 비용이 든 것을 놓쳤습니다.
Nemo157

5

파이썬-122 자

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 자

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

입력하지 않고 동사로 정의되었으므로 사양을 완전히 충족시키지 못하지만 나중에 어쨌든 그것을 다루기 위해 게시하고 있습니다.

용법:

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

4

펄, 95 자

Perl 5.010, 다음으로 실행 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

파이썬 - 144 개 143 140 136 125 문자

아마도 최고는 아니지만 어이 :

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()))

허, 나는 그런 것을 게시하려고했습니다. raw_input을 변수 3 자 정도의 문자에 할당 할 수 있습니다.
Juan

3

골프 스크립트-65 자

여전히 더 골프를 쳐야합니다. 현재 T는 텍스트이고 K는 키, L은 문자 목록입니다.

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

펄, 115 자

$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

골프 스크립트-92 자

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

아마도 필요한 것보다 훨씬 길 것입니다. 여전히 GS를 둘러 보려고합니다.

여기에 "ungolfed"와 댓글 버전

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

나열된 VB.NET 점수를 능가하지는 못합니다 (그러나 점점 가까워지고 있습니다).

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

용법:

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

팁을 준 Joey 에게 감사합니다 !


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)내가 알아볼 수있는 후보가 될 것입니다. VBA가 LF 줄 끝을 이해하는지 여부를 시험해보십시오. 적어도 하나의 공간이 x=x & Z(g)없어 질 수도 있습니다.
Joey

라인을 작성하는 다른 방법 : g=g+i*((Z(i)=d)-(Z(i)=c)) ( TrueVB에서 -1 이기 때문에 ). 작동 할 수 있습니다.
Joey

의견을 보내 주셔서 감사합니다, @Joey. 다른 개선 사항을 찾아서 추가
하겠습니다

2

C, 186

약간 늦었지만 .. (수평 스크롤 막대를 피하기 위해 줄이 끊어짐).

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

끊지 않은 줄

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

이 코드를 골프로 처리하는 과정에 대한 설명은 http://prob-slv.blogspot.com/2013/04/code-golf.html 에서 확인할 수 있습니다.


2

자바 스크립트 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

하스켈 (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 자

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

예를 들면 다음과 같습니다.

    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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.