Giải mã một bản mã Vigenère


28

Các Mật mã Vigenère là một mật mã polyalphabetic đơn giản mà về cơ bản áp dụng một trong những thuật toán mật mã Caesar, theo một chìa khóa. Về cơ bản các chữ cái trong khóa cho biết bảng chữ cái nào được sử dụng. Cuối cùng, có một công cụ đơn giản, được gọi là hình vuông Vigenère:

nhập mô tả hình ảnh ở đây

Ở đây mỗi hàng là một bảng chữ cái riêng, bắt đầu bằng chữ cái tương ứng của khóa. Các cột sau đó được sử dụng để xác định chữ cái được mã hóa. Giải mã hoạt động rất giống nhau, chỉ ngược lại.

Giả sử chúng ta muốn mã hóa chuỗi CODEGOLF. Chúng tôi cũng cần một chìa khóa. Trong trường hợp này, chìa khóa sẽ là FOOBAR. Khi khóa ngắn hơn bản rõ, chúng tôi sẽ mở rộng nó bằng cách lặp lại, do đó khóa thực tế chúng tôi sử dụng là FOOBARFO. Bây giờ chúng ta tìm kiếm chữ cái đầu tiên của khóa, đó là Ftìm bảng chữ cái. Nó bắt đầu, có lẽ không ngạc nhiên, với F. Bây giờ chúng ta tìm thấy cột có chữ cái đầu tiên của bản rõ và chữ cái kết quả là H. Đối với chữ cái thứ hai, chúng ta có Ochữ cái chính và chữ cái đơn giản, dẫn đến C. Tiếp tục theo cách đó cuối cùng chúng tôi cũng có được HCRFGFQT.

Bài tập

Nhiệm vụ của bạn bây giờ là giải mã các tin nhắn, đưa ra một khóa. Tuy nhiên, vì chúng ta đã phát triển từ thế kỷ 16 và có máy tính, ít nhất chúng ta nên hỗ trợ một bảng chữ cái lớn hơn một chút:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Việc xây dựng quảng trường Vigenère vẫn rất giống nhau và mật mã vẫn hoạt động theo cùng một cách. Nó chỉ là một chút ... khó sử dụng để cung cấp đầy đủ ở đây.

Đầu vào

Đầu vào được đưa ra trên đầu vào tiêu chuẩn dưới dạng hai dòng văn bản riêng biệt, mỗi dòng kết thúc bằng một ngắt dòng. Dòng đầu tiên chứa khóa trong khi dòng thứ hai chứa bản mã.

Đầu ra

Một dòng duy nhất, chứa thông điệp được giải mã.

Điều kiện chiến thắng

Vì mã hóa đôi khi được coi là một vũ khí, mã nên ngắn gọn để tạo điều kiện cho việc buôn lậu dễ ​​dàng. Càng ngắn càng tốt, vì nó làm giảm khả năng khám phá.

Mẫu đầu vào 1

Key
miQ2eEO

Sản lượng mẫu 1

Message

Mẫu đầu vào 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Sản lượng mẫu 2

ThisWorksEquallyWellWithNumbers123894576

Một tuần đã trôi qua. Các giải pháp ngắn nhất hiện nay đã được chấp nhận. Đối với những người quan tâm, trong cuộc thi của chúng tôi, chúng tôi đã có các bài dự thi và thời lượng sau:

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

Và các giải pháp riêng của chúng tôi không được xếp hạng với các giải pháp khác:

108 - Ruby
139 - PowerShell


Có vẻ như điều này có thể hữu ích để in hình vuông Vigenère.
Erik the Outgolfer

Câu trả lời:


10

Golfscript - 48 ký tự

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

Không có thủ thuật trong này!


+1 Tôi đã đi ngủ nghĩ rằng phải có một cách để giảm xuống ~ 50, bây giờ tôi thấy điều đó là có thể nhưng tôi có thể sẽ không quản lý nó bất cứ lúc nào
gnibbler

8

Tệp MS-DOS 16bit .COM - 87 byte

Nhị phân mã hóa Base64 ( theo liên kết này cho bộ giải mã )

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

Thông thường bạn tự viết mã nguồn ngắn để chơi gôn. Trong khi có lẽ không phải là không thể, tôi bằng cách nào đó nghi ngờ nó với điều này.
Joey

@Joey: Gì, bạn chưa bao giờ dùng tay mã hóa hướng dẫn mã máy! Những gì họ dạy trẻ những ngày này! ;-)
Skizz

Skizz: Tôi đã làm. Tuy nhiên, không phải ở Base64;) (chúng tôi đã có một lớp học vài năm trước, nơi chúng tôi phải viết chương trình cho một bộ lắp ráp Siemens 80C167 - và trong các bài kiểm tra cũng lắp ráp chúng thành mã máy. Tôi nghĩ về việc đào sâu kiến ​​thức đó cho Trình biên dịch Nhiệm vụ quine, nhưng chúng tôi không có cơ sở đầu ra [ít nhất, chúng khác nhau]).
Joey

@Joey: Base64 chỉ là tiện lợi cho những người dùng khác trên trang web này, thật dễ dàng để giải mã và lưu dưới dạng tệp nhị phân (liên kết trong câu trả lời có tùy chọn đó).
Skizz

À, xin lỗi. Tôi nghĩ rằng bạn đã đưa ra chiều dài của Base64. Chà, Chris đã từng đưa các nhân vật tùy ý vào một giải pháp và chỉ đưa ra một dấu thập phân bên cạnh câu trả lời của anh ta. Tôi đã làm tương tự trong dự báo thời tiết.
Joey

8

APL (45)

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

Giải trình:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: tạo bảng chữ cái (số ( ⎕D) theo các chữ cái ( ⎕A) theo các chữ cái viết thường ( ⎕UCS 96+⍳26, các giá trị unicode từ 97 đến 122).

  • 1-⍨⍞⍳⍨∆: đọc một dòng (khóa), tìm vị trí của từng ký tự trong bảng chữ cái và trừ đi một (các mảng được dựa trên một mặc định, do đó, việc thay đổi trực tiếp các giá trị đó sẽ dịch chuyển bảng chữ cái quá xa).

  • (⍴⍙←⍞)⍴: đọc một dòng khác (tin nhắn) và lặp lại các chỉ số của khóa để nó có độ dài của tin nhắn.
  • ⌽∘∆¨: xoay bảng chữ cái theo các chỉ số thuộc về phím
  • ⍙⍳⍨¨: tra cứu từng ký tự trong tin nhắn trong bảng chữ cái thay đổi tương ứng
  • ∆[... ]: Tra cứu các chỉ số đã cho trong bảng chữ cái bình thường, đưa ra các ký tự tương ứng.

6

Ruby - 132 127 122 109 100 ký tự

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

Sử dụng *$<thay vì $<.to_avà nội tuyến lambda để lưu một vài byte khác. - Ventero 5 phút trước
Joey

Cảm ơn @Joey, tôi đã kéo lambda ra để cứu nhân vật và bằng cách nào đó đã bỏ lỡ rằng nó thực sự có giá cao hơn.
Nemo157

5

Python - 122 ký tự

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 ký tự

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

Không hoàn toàn đáp ứng thông số kỹ thuật vì nó được định nghĩa là một động từ thay vì lấy đầu vào, nhưng dù sao tôi cũng sẽ đăng nó với ý định đấu tranh với nó vào một ngày sau đó.

Sử dụng:

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

4

Perl, 95 ký tự

Perl 5.010, chạy với 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

Con trăn - 144 143 140 136 125 ký tự

Có lẽ không phải là tốt nhất, nhưng hey:

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, tôi đã định đăng một cái gì đó như thế. Bạn có thể gán raw_input cho một biến, 3 ký tự trở lên.
Juan

3

Golfscript - 65 ký tự

Vẫn cần phải được chơi golf nhiều hơn. Hiện tại, T là văn bản, K là Khóa, L là danh sách các chữ cái

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 ký tự

$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 ký tự

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

Có lẽ lâu hơn nhiều so với nó cần phải được. Vẫn đang cố gắng để có được đầu của tôi xung quanh GS.

Đây là phiên bản "vô danh" và nhận xét

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

Không hoàn toàn đánh bại điểm VB.NET được liệt kê (nhưng tôi đang tiến gần):

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

Sử dụng:

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

Cảm ơn Joey cho tiền boa!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)sẽ là một ứng cử viên tôi có thể nhận ra. Cũng như thử xem liệu kết thúc dòng LF có được VBA hiểu hay không. Ít nhất một không gian trong x=x & Z(g)cũng có thể bị bỏ lại, tôi đoán vậy.
Joey

Một cách khác để viết dòng: g=g+i*((Z(i)=d)-(Z(i)=c)) (vì Truelà in1 trong VB). Có thể là nó hoạt động.
Joey

Cảm ơn đã phản hồi, @Joey. Tôi sẽ tìm kiếm bất kỳ cải tiến nào khác và thêm nó vào.
Gaffi

2

C, 186

Một chút muộn nhưng .. (dòng bị hỏng để tránh thanh cuộn ngang).

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

Đường không ngắt

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

Một cuộc thảo luận về quá trình chơi golf mã này có thể được tìm thấy ở đây: 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 ký tự

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

Ví dụ:

    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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.