解密Vigenère密文


28

根据一位密钥,Vigenère密码是一种简单的多字母密码,基本上使用了几种Caesar密码之一。通常,键中的字母表示要使用的移位字母。为此,有一个简单的工具称为维格涅尔广场:

在此处输入图片说明

这里的每一行都是一个单独的字母,从键的相应字母开始。然后,这些列用于确定密文字母。解密的工作方式几乎相同,反之亦然。

假设我们要加密字符串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


看起来对打印维格涅尔广场很有用。
Erik the Outgolfer

Answers:


10

Golfscript-48个字符

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

在这没有技巧!


+1我上床睡觉,以为一定有办法将其降低到
〜50

8

MS-DOS 16bit .COM文件-87字节

Base64编码的二进制文件(此链接用于解码器

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

通常,您自己编写打高尔夫球的简短源代码。虽然可能并非不可能,但我对此有些怀疑。
乔伊,

@Joey:什么,您从未手工编码过机器代码指令!这些天他们在教年轻人什么!;-)
Skizz

Skizz:我做到了。不过不是在Base64上;)(几年前,我们有一堂课,必须在汇编器中为Siemens 80C167编写程序–并且在考试中还将它们汇编为机器代码。我考虑过为汇编器挖掘这些知识艰巨的任务,但我们没有输出工具(至少,它们有所不同))。
乔伊,

@Joey:Base64只是该站点上其他用户的便利,它很容易解码并保存为二进制文件(答案中的链接具有该选项)。
Skizz

啊,对不起。我以为您会给出Base64的长度。好吧,克里斯曾经在解决方案中加入了任意字符,并且除了回答外还给出了一个十六进制转储。我在天气预报中也做过类似的事情。
乔伊,

8

APL(45)

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

说明:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26:生成字母(数字(⎕D)跟随字母(⎕A)跟随小写字母(⎕UCS 96+⍳26,从97到122的unicode值)。

  • 1-⍨⍞⍳⍨∆:读取一行(键),找到每个字符在字母表中的位置,然后减去一个(默认情况下,数组是基于1的,因此直接移位这些值会使字母表移位太远)。

  • (⍴⍙←⍞)⍴:读取另一行(消息),然后重复键的索引,使其具有消息的长度。
  • ⌽∘∆¨:按属于键的索引旋转字母
  • ⍙⍳⍨¨:以相应的移位字母查找消息中的每个字符
  • ∆[... ]:以普通字母查找给定的索引,并给出相应的字符。

6

Ruby- 132127122109100个字符

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_alambda并将其内联以保存另外几个字节。– Ventero 5分钟前
Joey

谢谢@Joey,我拉出那个lambda来保存字符,却以某种方式错过了它实际上要花更多的钱。
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

蟒- 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个字符左右的变量。
胡安

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。

继承人的“ unolfed”和评论版本

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

感谢乔伊的提示!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)我会发现一个候选人。以及尝试VBA是否了解LF线的末端。x=x & Z(g)我想至少也可以留出一个空格。
乔伊,

编写该行的另一种方式:(g=g+i*((Z(i)=d)-(Z(i)=c)) 因为True在VB中为-1)。可能是可行的。
乔伊,

感谢您的反馈,@ 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

哈斯克尔(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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.