2

我已经成功实现了一个程序,将明文转换为 [amsco cipher] ( http://www.thonky.com/kryptos/amsco-cipher/ ) 的密文。但是,我无法了解如何将密文转换为纯文本。我们如何确定将密码转换为纯文本的列的长度(或每列的行数)?例如,如果密文是 EMAAE HUMBA LMNRE AUDSR RTSUN WHAVP TOEMH KITVE DGEUS TEATO SHOSO YHNME EKLAI并且列密钥是 35142,那么在列“1”下,起始字母是 E,同一列中的下一行将是 MA。列号“1”中的第三行将具有“A”,依此类推。但是,我们如何确定每列的总行数?

谢谢。

4

2 回答 2

2

我认为,最简单的方法就是编写一个循环来执行您对编码所做的操作。所以它为每一列加起来 1s 和 2s 直到没有剩下的字母。

这是一个解码文本以显示我的意思的程序(它是用 python 3 编写的):

words = ['EMAAE', 'HUMBA', 'LMNRE', 'AUDSR', 'RTSUN', 'WHAVP', 
         'TOEMH', 'KITVE', 'DGEUS', 'TEATO', 'SHOSO', 'YHNME', 'EKLAI']

ctext = ''.join(words)
l = len(ctext)
print('\ntotal chars', l)

key = '35142'
n = len(key)
print('\nkey length', n)

# here we do exactly the same as what you did to encode, except we just
# count the letters.  so chars[x] is the number of characters in column x,
# which starts at 0 and is added 1 or 2 on each line.
chars = [0] * n
remaining = l
ichar = 0
chunk = 0
while remaining > 0:
    k = min(chunk+1, remaining)
    chars[ichar] += k
    remaining -= k
    ichar = (ichar + 1) % n  # this indexes the columns 0..n-1,0..n-1,...
    chunk = (chunk + 1) % 2  # this goes 0,1,0,1,... and we +1 above

# now we have the number of characters in each column, so display that
print('\nkey digit and number of characters')
for i, digit in enumerate(key):
    print(digit, chars[i])

# but the ordering in the encrypted data is different, so we re-order to
# match that.  this uses a bit of a trick in python - if we order a list of
# pairs (a,b) then is it ordered by the first thing in the pair (the key 
# digit) here.  so we order by the key digit, but also re-arrange the
# columns sizes.
digitsandchars = [(digit, chars[i]) for i, digit in enumerate(key)]
print('\nbefore sorting', digitsandchars)
digitsandchars = sorted(digitsandchars)
print('after sorting', digitsandchars)

# now that we have the columns sizes in the right order we can cut up the
# text into the columns
columns = [''] * n
for i in range(n):
    digit, nchars = digitsandchars[i]
    columns[i] = ctext[:nchars]
    ctext = ctext[nchars:]
    print('digit', digit, 'column', columns[i])

# now switch the columns back to the order they were originally
ordered = [columns[int(key[i])-1] for i in range(n)]
print('\nordered columns', ordered)

# and finally we can decode by doing the same process as before - we pick
# off 1 or 2 characters from each column until we have nothing left.
print('\ndecode')
icolumn = 0
remaining = l
chunk = 0
while remaining > 0:
    column = ordered[icolumn]
    k = min(chunk+1, remaining)
    print(column[:k], end='')  # print the first k characters
    remaining -= k
    ordered[icolumn] = column[k:]  # remove the printed characters
    icolumn = (icolumn + 1) % n
    chunk = (chunk + 1) % 2
print()

这是输出:

total chars 65

key length 5

key digit and number of characters
3 13
5 14
1 13
4 13
2 12

before sorting [('3', 13), ('5', 14), ('1', 13), ('4', 13), ('2', 12)]
after sorting [('1', 13), ('2', 12), ('3', 13), ('4', 13), ('5', 14)]
digit 1 column EMAAEHUMBALMN
digit 2 column REAUDSRRTSUN
digit 3 column WHAVPTOEMHKIT
digit 4 column VEDGEUSTEATOS
digit 5 column HOSOYHNMEEKLAI

ordered columns ['WHAVPTOEMHKIT', 'HOSOYHNMEEKLAI', 'EMAAEHUMBALMN', 'VEDGEUSTEATOS', 'REAUDSRRTSUN']

decode
WHOEVERHASMADEAVOYAGEUPTHEHUDSONMUSTREMEMBERTHEKAATSKILLMOUNTAINS
于 2013-07-12T20:32:59.040 回答
0

我测试了 Andrew 的代码,它似乎并不适用于所有情况。顺便说一句,我最近正在研究 Amsco 密码,如果你知道密钥,有一个相当简单的方法可以解密密文:

  1. 您需要执行的第一步是将密文写入列中,就好像您正在对其进行加密一样

  2. 使用这种格式,您就可以知道原始纯文本的每一列中必须包含多少个字母。

  3. 你从你的密文中知道,前一个或两个字母会出现在标有 1 的列中。所以找到这一列(记住第 1 列可能不一定是第一列,取决于你的密钥),查看字母格式,然后添加字母。例如,如果您知道标记为 1 的列的格式为:

    AB

    C

    F

    G

然后你只需要遍历前七个字母,并根据上述格式将它们添加到第一列。

4.对其余列重复此方法,完成后逐行读取字母,得到原始纯文本。

我的代码都在工作,但是有一场比赛正在进行,其中一项任务涉及这个密码。我会在两周内完成。

于 2015-12-06T23:50:24.590 回答