ถอดรหัสVigenère ciphertext


28

Vigenere ตัวเลขเป็นตัวเลข polyalphabetic ง่ายๆที่พื้นใช้หนึ่งยันต์จักรพรรดิหลายตามคีย์ โดยพื้นฐานแล้วตัวอักษรในปุ่มจะระบุว่าจะใช้ตัวอักษรใดในการเลื่อน ด้วยเหตุนี้จึงมีเครื่องมือง่าย ๆ ที่เรียกว่าVigenère square:

ป้อนคำอธิบายรูปภาพที่นี่

ที่นี่แต่ละแถวเป็นตัวอักษรแยกเริ่มต้นด้วยตัวอักษรที่เกี่ยวข้องของคีย์ คอลัมน์จะถูกใช้เพื่อกำหนดตัวอักษรที่เข้ารหัส การถอดรหัสใช้งานได้เหมือนกันมากในทางกลับกันเท่านั้น

CODEGOLFสมมติว่าเราต้องการที่จะเข้ารหัสสตริง เรายังต้องการกุญแจ FOOBARในกรณีนี้ที่สำคัญจะต้องเป็น FOOBARFOเมื่อที่สำคัญคือสั้นกว่าธรรมดาที่เราขยายได้โดยการทำซ้ำจึงเป็นกุญแจสำคัญที่เกิดขึ้นจริงที่เราใช้คือ ตอนนี้เราค้นหาตัวอักษรตัวแรกของกุญแจซึ่งก็คือFการค้นหาตัวอักษร Fมันเริ่มต้นอาจจะแปลกใจกับ Hตอนนี้เราได้พบกับคอลัมน์ที่มีอักษรตัวแรกของเท็กซ์และตัวอักษรที่เกิดขึ้นคือ สำหรับจดหมายที่สองที่เรามีเป็นตัวอักษรที่สำคัญและตัวอักษรข้อความธรรมดาที่เกิดขึ้นในO อย่างต่อเนื่องวิธีการที่ในที่สุดเราก็จะได้รับCHCRFGFQT

งาน

ตอนนี้งานของคุณคือการถอดรหัสข้อความให้รหัส อย่างไรก็ตามเนื่องจากเราเติบโตเกินกว่าศตวรรษที่ 16 และมีคอมพิวเตอร์อย่างน้อยเราควรสนับสนุนตัวอักษรขนาดใหญ่กว่าเล็กน้อย:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

การก่อสร้างจัตุรัสVigenèreยังคงเหมือนเดิมมากและศูนย์ยังคงทำงานในลักษณะเดียวกัน เป็นเพียงเล็กน้อย ... ไม่เต็มใจที่จะให้ที่นี่เต็ม

อินพุต

อินพุตได้รับจากอินพุตมาตรฐานเป็นข้อความสองบรรทัดแยกกันโดยแต่ละบรรทัดจะถูกยกเลิกโดยการขึ้นบรรทัดใหม่ บรรทัดแรกมีคีย์ในขณะที่บรรทัดที่สองประกอบด้วย ciphertext

เอาท์พุต

บรรทัดเดียวที่มีข้อความที่ถอดรหัส

สภาพการชนะ

เนื่องจากการเข้ารหัสบางครั้งถือเป็นอาวุธรหัสควรสั้นเพื่ออำนวยความสะดวกในการลักลอบขนง่าย ยิ่งสั้นยิ่งดีก็ยิ่งลดโอกาสในการค้นพบน้อยลง

ตัวอย่างอินพุต 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 Square
Erik the Outgolfer

คำตอบ:


10

Golfscript - 48 ตัวอักษร

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

ไม่มีลูกเล่นในเกมนี้!


+1 ฉันเข้านอนคิดว่าจะต้องมีวิธีที่จะลดระดับลงถึง ~ 50 ตอนนี้ฉันเห็นว่าเป็นไปได้ แต่ฉันอาจจะไม่สามารถจัดการได้ตลอดเวลาเร็ว ๆ นี้
gnibbler

8

ไฟล์. com 16 บิต MS-DOS - 87 ไบต์

ไบนารีที่เข้ารหัส Base64 ( ตามลิงก์นี้เพื่อถอดรหัส )

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

โดยปกติคุณจะเขียนซอร์สโค้ดสั้น ๆ เพื่อเล่นกอล์ฟ แม้ว่าฉันจะไม่เป็นไปไม่ได้ แต่ฉันก็ยังสงสัยในข้อนี้
Joey

@ โจอี้: อะไรคุณไม่เคยส่งรหัสเครื่องคำแนะนำ! วันนี้พวกเขาสอนอะไรเด็ก ๆ ! ;-)
Skizz

Skizz: ฉันทำ แต่ไม่ได้อยู่ใน Base64;) (เรามีคลาสเมื่อสองสามปีก่อนที่เราต้องเขียนโปรแกรมสำหรับซีเมนส์ 80C167 ในแอสเซมเบลอร์ - และในการสอบก็รวบรวมมันไว้ในรหัสเครื่องด้วย งาน Quine แต่เราไม่มีสิ่งอำนวยความสะดวกเอาท์พุท
Joey

@Joey: Base64 เป็นเพียงความสะดวกสบายสำหรับผู้ใช้อื่น ๆ ในเว็บไซต์นี้มันง่ายในการถอดรหัสและบันทึกเป็นไฟล์ไบนารี (ลิงก์ในคำตอบมีตัวเลือกนั้น)
Skizz

อ๊ะขอโทษ ฉันคิดว่าคุณจะให้ความยาวของ Base64 คริสเคยรวมตัวละครโดยพลการไว้ในโซลูชันและให้ 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

Ruby - 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

ขอบคุณ @ โจอี้ฉันดึงแลมบ์ดานั้นออกมาเพื่อบันทึกตัวละคร แต่ก็พลาดไปว่ามันแพงกว่าจริง ๆ
Nemo157

5

Python 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

Perl, 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

Python - 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

Golfscript - 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

Perl, 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

Golfscript - 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)) (เนื่องจากTrue−1 ใน VB) อาจเป็นไปได้ว่ามันใช้งานได้
Joey

ขอบคุณสำหรับความคิดเห็น @Joey ฉันจะมองหาการปรับปรุงอื่น ๆ และเพิ่มสิ่งต่อไปนี้
Gaffi

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

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 ตัวอักษร

[:{&{.&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.