Desen analizi ile şifre çözme


11

Size çok basit bir ikame şifresi kullanılarak şifrelenmiş şifreli bir dize verilir.

Sorun

Şifrenin ne olduğunu bilmiyorsunuz, ancak şifre metninin İngilizce olduğunu ve İngilizce'deki en sık kullanılan harflerin bu sırada etaoinshrdlucmfwypvbgkqjxz olduğunu biliyorsunuz . İzin verilen karakterler büyük harf ve boşluktur. Tek harflerden başlayarak temel analiz yapabilirsiniz, ancak daha karmaşık çok harfli analize geçebilirsiniz - örneğin, U neredeyse her zaman Q'yu takip eder ve yalnızca belirli harfler art arda iki kez gelebilir.

Örnekler

clear : SUBMARINE TO ATTACK THE DOVER WAREHOUSE AND PORT ON TUESDAY SUNRISE
cipher: ZOQ DUPAEYSRYDSSDXVYSHEYNRBEUYLDUEHROZEYDANYKRUSYRAYSOEZNDMYZOAUPZE

clear : THE QUICK BROWN FOX BEING QUITE FAST JUMPED OVER THE LAZY DOG QUITE NICELY
cipher: TNAEPDHIGEMZQJLEVQBEMAHL EPDHTAEVXWTEODYUASEQKAZETNAERXFCESQ EPDHTAELHIARC

clear : BUFFALO BUFFALO BUFFALO BUFFALO BUFFALO BUFFALO BUFFALO
cipher: HV  WRPDHV  WRPDHV  WRPDHV  WRPDHV  WRPDHV  WRPDHV  WRP

Zorluklar

Bu şifrelerin her birindeki metnin şifresini çözüp çözemeyeceğinize bakın:

  • SVNXIFCXYCFSXKVVZXIHXHERDXEIYRAKXZCOFSWHCZXHERDXBNRHCXZR RONQHXORWECFHCUH
  • SOFPTGFIFBOKJPHLBFPKHZUGLSOJPLIPKBPKHZUGLSOJPMOLEOPWFSFGJLBFIPMOLEOPXULBSIPLBP KBPBPWLIJFBILUBKHPGKISFG
  • TMBWFYAQFAZYCUOYJOBOHATMCYNIAOQW Q JAXOYCOCYCHAACOCYCAHGOVYLAOEGOTMBWFYAOBFF ACOBHOKBZYKOYCHAUWBHAXOQW XITHJOV WOXWYLYCU
  • FTRMKRGVRFMHSZVRWHRSFMFLMBNGKMGTHGBRSMKROKLSHSZMHKMMMMMRVVLVMPRKKOZRMFVDSGOFRW

Her biri için ikame matrisleri ve açık metinlerim var, ancak onları ancak çok zorlaşırsa veya biri anlamazsa ortaya koyacağım.

En çok mesajın şifresini başarıyla çözebilen çözüm kazanır. İki çözüm eşit derecede iyi ise, oy sayıları ile karar verilecektir.


3
»En zarif« ne tanımlar? Sanırım bu Chris'in zaten 99 şişede itiraz ettiği şeyle aynı. Yargılaması oldukça zor olan öznel bir kriter.
Joey

@Joey Most upvotes? Topluluk karar versin.
Thomas O

2
Re "en upvotes": Ben bu yazı popülerlik yarışma yazı haline görmek için mutsuz değilim, en azından yazı aksi mükemmel olduğu için; tüm konu hakkındaki düşüncelerim için meta.codegolf.stackexchange.com/questions/110/… adresine bakın .
Chris Jester-Young

2
Burada "zarif" ne anlama geliyor? En iyi big-O performansı?
gnibbler

1
@ Bass5098, hayır. Frekans analizine daha dayanıklı hale getirilmesi zorlaştırılmış sadece zor bir şifreleme metnidir.
Thomas O

Yanıtlar:


9

piton

Tüm gizli cümleleri anladım, ama onları buraya göndermeyeceğim. İsterseniz kodu çalıştırın.

Kod, bir boşluk karakteri seçerek, her sözcük için tüm olası ikameleri numaralandırarak ve ardından uyumlu ikameleri arayarak çalışır. Ayrıca, bazı sözlük dışı kelimelerin açık metindeki yazım hatalarıyla başa çıkmasına izin verir :)

Http://wordlist.sourceforge.net/ adresinden büyük bir sözlük (~ 500K kelime) kullandım .

import sys,re

# get input
message = sys.argv[1]

# read in lexicon of words
# download scowl version 7.1
# mk-list english 95 > wordlist
lexicon = set()
roman_only = re.compile('^[A-Z]*$')
for word in open('wordlist').read().upper().split():
  word=word.replace("'",'')
  if roman_only.match(word): lexicon.add(word)

histogram={}
for c in message: histogram[c]=0
for c in message: histogram[c]+=1
frequency_order = map(lambda x:x[1], sorted([(f,c) for c,f in histogram.items()])[::-1])

# returns true if the two maps are compatible.
# they are compatible if the mappings agree wherever they are defined,
# and no two different args map to the same value.
def mergeable_maps(map1, map2):
  agreements = 0
  for c in map1:
    if c in map2:
      if map1[c] != map2[c]: return False
      agreements += 1
  return len(set(map1.values() + map2.values())) == len(map1) + len(map2) - agreements

def merge_maps(map1, map2):
  m = {}
  for (c,d) in map1.items(): m[c]=d
  for (c,d) in map2.items(): m[c]=d
  return m

def search(map, word_maps, outside_lexicon_allowance, words_outside_lexicon):
  cleartext = ''.join(map[x] if x in map else '?' for x in message)
  #print 'trying', cleartext

  # pick a word to try next
  best_word = None
  best_score = 1e9
  for (word,subs) in word_maps.items():
    if word in words_outside_lexicon: continue
    compatible_subs=0
    for sub in subs:
      if mergeable_maps(map, sub): compatible_subs += 1
    unassigned_chars = 0
    for c in word:
      if c not in map: unassigned_chars += 1  #TODO: duplicates?
    if compatible_subs == 0: score = 0
    elif unassigned_chars == 0: score = 1e9
    else: score = 1.0 * compatible_subs / unassigned_chars   # TODO: tweak?
    if score < best_score:
      best_score = score
      best_word = word
  if not best_word:  # no words with unset characters, except possibly the outside lexicon ones
    print cleartext,[''.join(map[x] if x in map else '?' for x in word) for word in words_outside_lexicon]
    return True

  # use all compatible maps for the chosen word
  r = False
  for sub in word_maps[best_word]:
    if not mergeable_maps(map, sub): continue
    r |= search(merge_maps(map, sub), word_maps, outside_lexicon_allowance, words_outside_lexicon)

  # maybe this word is outside our lexicon
  if outside_lexicon_allowance > 0:
    r |= search(map, word_maps, outside_lexicon_allowance - 1, words_outside_lexicon + [best_word])
  return r

for outside_lexicon_allowance in xrange(3):
  # assign the space character first
  for space in frequency_order:
    words = [w for w in message.split(space) if w != '']
    if reduce(lambda x,y:x|y, [len(w)>20 for w in words]): continue  # obviously bad spaces

    # find all valid substitution maps for each word
    word_maps={}
    for word in words:
      n = len(word)
      maps = []
      for c in lexicon:
        if len(c) != n: continue
        m = {}
        ok = 1
        for i in xrange(n):
          if word[i] in m:                      # repeat letter
            if m[word[i]] != c[i]: ok=0; break  # repeat letters map to same thing
          elif c[i] in m.values(): ok=0; break  # different letters map to different things
          else: m[word[i]]=c[i]
        if ok: maps.append(m);
      word_maps[word]=maps

    # look for a solution
    if search({space:' '}, word_maps, outside_lexicon_allowance, []): sys.exit(0)

print 'I give up.'

1

PHP (Eksik)

Bu, sorudaki harf frekansı bilgileri ve verilen kelimedeki en güvenilir harflere dayanan düzenli ifadelerle eşleşen bir sözlük sözlüğü kullanarak çalışan eksik bir PHP çözümüdür.

Şu anda sözlük oldukça küçük ama uygun genişleme ile sonuçların iyileşeceğini tahmin ediyorum. Kısmi eşleşme olasılığını düşündüm, ancak mevcut sözlükte bu, sonuçlarda iyileşme yerine bozulma ile sonuçlanıyor.

Mevcut küçük sözlükte bile dördüncü mesajın neyi kodladığını rahatlıkla söyleyebilirim.

#!/usr/bin/php
<?php

    if($argv[1]) {

        $cipher = $argv[1];

        // Dictionary
        $words = explode("/", "the/to/on/and/in/is/secret/message");
        $guess = explode("/", "..e/t./o./a../i./.s/.e..et/.ess..e");

        $az = str_split("_etaoinshrdlucmfwypvbgkqjxz");

        // Build table
        for($i=0; $i<strlen($cipher); $i++) {
            $table[$cipher{$i}]++;
        }
        arsort($table);

        // Do default guesses
        $result = str_replace("_", " ", str_replace(array_keys($table), $az, $cipher));

        // Apply dictionary
        $cw = count($words);
        for($i=0; $i<$cw*2; $i++) {
            $tokens = explode(" ", $result);
            foreach($tokens as $t) {
                if(preg_match("/^" . $guess[$i%$cw] . "$/", $t)) {
                    $result = deenc($words[$i%$cw], $t, $result);
                    echo $t . ' -> ' . $words[$i%$cw] . "\n";
                    break;
                }
            }
        }

        // Show best guess
        echo $result . "\n";

    } else {

        echo "Usage: " . $argv[0] . " [cipher text]\n";

    }

    // Quick (non-destructive) replace tool
    function deenc($word, $enc, $string) {
        $string = str_replace(str_split($enc), str_split(strtoupper($word)), $string);
        $string = str_replace(str_split($word), str_split($enc), $string);
        return strtolower($string);
    }

?>

İçinde bir sistem varsa / usr / share / dict / words komutunu kullanmayı deneyin.
Keith Randall
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.