该VIC密码是有史以来设计最为复杂的铅笔和纸密码之一。1950年代由苏联间谍ReinoHäyhänen使用,代号为“ VICTOR”,其主要原理是通过迷惑实现安全。一个很多混淆。
您的任务是编写将接收消息并使用VIC密码对其进行编码的程序或函数。我还在这里发布了VIC密码解码器挑战赛。如果以下任何说明不清楚,请随时在评论中询问。该说明改编自该站点。
编码VIC密码
制备
您将需要五个输入:
- 明文消息
- 包含您语言中最常见字母的简短关键字或短语
- 关键短语,例如报价单或歌曲中的一行(至少20个字符)
- 日期(或其他六位数或更多的数字)
- 个人代理号码
实际上,这最后四个应该由发送方和接收方事先商定,包括在编码中是否使用发送方或接收方的代理号码。
我的示例消息将是: We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
我们将使用英语编码(尽管您可以使用喜欢的任何语言和字母),而英语字母中最常见的字母是A, E, I, N, O, R, S, T
。我将使用关键字SENATORI
。
我的主要用语是理查德·费曼(Richard Feynman)的一句话:“第一个原则是,您切勿欺骗自己,而您是最容易欺骗的人。”
作为日期,我将使用2016年7月31日(格式为3172016
),也就是我撰写此说明的日期。
我为自己选择的个人号码是9
。
步骤摘要
- 派生用于以下步骤的中间键。
- 构造并应用跨界棋盘。
- 构造并应用第一个换位表。
- 构造并应用第二个(中断的)换位表。
- 通过插入消息指示符组来完成消息。
子机制
在深入探讨该问题之前,还有两件事需要解释:链添加和排序的过程。
链加法也称为滞后斐波那契生成器,其工作原理是采用起始数字序列,将前两位数字相加而不携带(然后将它们加在一起mod 10
),然后将结果附加到末尾。例如:
79081
7 + 9 = 6
790816
9 + 0 = 9
7908169
0 + 8 = 8
79081698
8 + 1 = 9
790816989
1 + 6 = 7
7908169897
... and so on
顺序化实质上是采用字母或数字的序列,并按字母/数字顺序对其进行标记。重复项从左到右标记。例如:
E X A M P L E
0 # A
1 0 2 # Es
1 0 3 2 # L
1 0 4 3 2 # M
1 0 4 5 3 2 # P
1 6 0 4 5 3 2 # X
3 3 0 5 8 4 2 0 4 7 5 4 8 1
0 1 # 0s
0 1 2 # 1
0 3 1 2 # 2
4 5 0 3 1 2 # 3s
4 5 0 6 3 1 7 8 2 # 4s
4 5 0 9 6 3 1 7 10 8 2 # 5s
4 5 0 9 6 3 1 7 11 10 8 2 # 7
4 5 0 9 12 6 3 1 7 11 10 8 13 2 # 8s
我在这里使用零索引,但是您喜欢索引。
1.中级键
将关键字词组的前20个字母分成10组,每组分别进行序列化,我们将其称为S1
和S2
。
THEFIRSTPR
S1: 8201357946
INCIPLEIST
S2: 2603751489
选择一个随机的5位数字的消息标识符M
(如果您愿意,可以是输入之一):
M = 47921
减,不借用(减法mod 10
),关键日期的前五位3172016
来自M
:
M 47921
date - 31720
= 16201
链式添加结果,直到十位数为止:
1620178218
将这些数字加到S1
(不带或)上mod 10
,以获得G
:
1620178218
S1 + 8201357946
G = 9821425154
在上方S2
,输入序列0123456789。找到序列0123456789中的每个数字,G
并将其替换为中位于其正下方的数字S2
。结果是T
。
0123456789
S2 2603751489
G 9821425154
T 9806705657
使用链加法扩展T
到60位数字。
9806705657
becomes
980670565778637511245490262369939288595822106344304316978734
这最后的50位数字,每行十位数字,分为五行,构成了该U
块。
T 9806705657
U 7863751124
5490262369
9392885958
2210634430
4316978734
块的最后两个非等位数U
分别添加到座席的个人号码上,以给出两个变位的宽度,p
和q
。
9 + 3 = 12(p,第一个换位宽度)9 + 4 = 13(q,第二个换位宽度)
序列化T
并使用此序列U
从上到下将块的各列复制到新的数字行中V
。
T 9806705657
seqT 9804612537
U 7863751124
5490262369
9392885958
2210634430
4316978734
V 69911 56837 12548 26533 30206 13947 72869 49804 84323 75924
顺序排列第一个p
数字以获取第一个换位的键,K1
随后的q
数字为第二个换位的键K2
。
First 12 6 9 9 1 1 5 6 8 3 7 1 2
K1 6 10 11 0 1 5 7 9 4 8 2 3
Next 13 5 4 8 2 6 5 3 3 3 0 2 0 6
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
最后,按顺序对U
块的最后一行进行获取C
,以获取跨棋盘的列标题:
U5 4316978734
C 3105968724
2.跨棋盘
首先,我将给出示例棋盘格,然后解释以这种方式创建棋盘格的原理:
3 1 0 5 9 6 8 7 2 4
S E N A T O R I
2 B D G J L P U W Y .
4 C F H K M Q V X Z #
第一行字母是我们的短关键字SENATORI
。您的关键字可以是任何没有重复的字符串,但是由于它定义了棋盘格的第一行,因此请明智地选择。关键字上方是C
,其余各行是您选择的字母顺序的其余部分。就我而言,我在棋盘格中填充了其余的拉丁字母,标点符号.
和标界数字的标记#
。本质上,棋盘是一种奇特的替换密码。例如,“ E”将替换为1
,“ W”将替换为27
。
一旦使用此棋盘对明文消息进行了编码,但是首先,我们需要通过在任意位置将其分割成大写来使消息的开头不那么明显。为了表示另一个原始开始,我们使用两个句号..
We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
变成
HING ELSE. MOVE TO SAFEHOUSE FOXTROT#3#.. WE ARE
DISCOVERED. TAKE WHAT YOU CAN. BURN EVERYT
我们使用棋盘格进行编码,从而为我们提供:
407020 1293124 496481 96 354114062831 416479869443442424 271 581
2173436481812124 95451 274059 22628 435024 232880 14818229
如果消息的长度不能被5整除,我们将添加一些空字符来填充消息。我们的消息是109位数字长,因此我将添加一个空值:“ 4”。
40702 01293 12449 64819 63541 14062 83141 64798 69443 44242 42715
81217 34364 81812 12495 45127 40592 26284 35024 23288 01481 82294
注意:由于我的示例消息不包含数字,因此在这里我要说的是,您可以指定as #3#
,其编码如下44344
。
3.第一次换位
通过K1
在中间键的相同长度的行中写入(在“中间键”部分中),后跟上一步中的编码消息,来创建换位表:
K1 6 10 11 0 1 5 7 9 4 8 2 3
4 0 7 0 2 0 1 2 9 3 1 2
4 4 9 6 4 8 1 9 6 3 5 4
1 1 4 0 6 2 8 3 1 4 1 6
4 7 9 8 6 9 4 4 3 4 4 2
4 2 4 2 7 1 5 8 1 2 1 7
3 4 3 6 4 8 1 8 1 2 1 2
4 9 5 4 5 1 2 7 4 0 5 9
2 2 6 2 8 4 3 5 0 2 4 2
3 2 8 8 0 1 4 8 1 8 2 2
9 4
按照编号顺序按编号的列,我们得到:
060826428 246674580 151411542 246272922 961311401 082918141
4414434239 118451234 334422028 293488758 0417249224 794943568
4.第二次换位
第一次换位相对简单。但是,这是一个中断的换位。破坏模式由桌子和钥匙的宽度决定。在我们的示例中,我们有110位数字和13列,这意味着我们将有8个完整的行和6个剩余项。我们开始填充第一行,但在第0列处停止,然后继续进行以下操作:
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 stop at 0
2 4 6 6 7 4 5 8 0 1 continue in a triangle pattern
5 1 4 1 1 5 4 2 2 4 6
2 7 2 9 2 2 9 6 1 3 1 1
4 0 1 0 8 2 9 1 8 1 4 1 4 until the end
4 1 4 4 3 4 2 3 9 1 1 restart and stop at 1
8 4 5 1 2 3 4 3 3 4 4 2
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 restart and stop at 2
然后,我们用剩余的数字填充最后几个空格。
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 7 2 4 9
2 4 6 6 7 4 5 8 0 1 2 2 4
5 1 4 1 1 5 4 2 2 4 6 7 9
2 7 2 9 2 2 9 6 1 3 1 1 4
4 0 1 0 8 2 9 1 8 1 4 1 4
4 1 4 4 3 4 2 3 9 1 1 9 4
8 4 5 1 2 3 4 3 3 4 4 2 3
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 5 6 8
现在,我们以与第一次换位完全相同的方式读取列。
71431148 42711925 861904185 22614147 45499243 28261334 80218938
641701404 025244820 645224398 271283226 94944438 064214521
并将所有内容分成5位数字组:
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189
38641 70140 40252 44820 64522 43982 71283 22694 94443 80642 14521
5.完成消息
最后一步是将我们的随机消息标识符47921
插入消息本身。关键日期的最后一位数字6
指示组距末尾的距离。
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189 38641
70140 40252 44820 64522 43982 47921 71283 22694 94443 80642 14521
挑战说明
- 给您至少五个输入:消息,字母关键字,关键词,日期和个人号码。您可能包括两个附加输入:随机消息标识符和填充消息所需的空值,否则您的函数可能会自行生成一些随机数。
- 您可以假定所有输入均有效,并带有正确的数字和字母数量(5位消息标识符,关键字至少20位,依此类推)。您可以假定您的字符串(消息和关键字)已经删除了所有标点符号和空格(版本中允许的除外),并且数字已经用数字符号分隔。
- 第一个关键字中不应包含重复的字母,并且在您的代码中,您可能会假定它从来没有重复的字母。
- 您使用的编码语言并不重要,只要该语言已经存在,字母已经存在并且您可以指定答案中使用的语言即可。
- 无论您跨过棋盘使用哪种字母,都可以添加或删除符号以将棋盘填充出来。指定您使用这些符号的目的(例如,标点符号,单独的“消息开始”符号,常见单词的符号)。您可以完全放弃数字符号,并使用数字符号用于其他用途的插槽来拼写数字,或在棋盘中包含每个数字。请指定您在答案中使用的棋盘格。
- 输出应该是由空格分隔的五位数字组的字符串,五位整数的列表或类似内容。
- 我
0123456789
在示例中使用了零索引。1234567890
只要指定使用的内容,您就可以在答案中使用1-indexing和或其他系统。
这是一篇很长的文章,我大部分都是手工撰写的,因此,如果这篇文章中有任何令人困惑的部分,或者我的计数和移调有误,请告诉我。祝你好运,打高尔夫球!
without borrowing
和”的意思without carrying
吗?你的意思是加上和减去mod 10
,即(6+7) mod 10 = 3
和(6-8) mod 10 = 8
?
adding the first two digits without adding
你是说背负吗?