تحليل التردد: نقوم بتحليل إحدى المهام المفضلة للمشاركين في المرحلة عبر الإنترنت من NeoQUEST-2020


ننشر اليوم مهمة Wright-Up NeoQUEST-2020 ، التي كتب عنها المشاركون لدينا: "4 Task mega cool" و "The Best task of the Olympiad".
على الرغم من البساطة الواضحة ، أكمل 8 أشخاص فقط هذه المهمة! والآن يمكنك التعرف عليه بشكل أفضل ، لهذا - نرحب تحت القط!


لذا ، فإن المشاركين مدعوون لتنزيل التسجيل الصوتي . دقيقة من الاستماع كافية لفهم أن شفرة مورس لا تشم حتى هنا ، تمامًا مثل الكلمات ذات المغزى في التسجيل الصوتي أيضًا. لذلك ، ننهي التعذيب بالاستماع ونبدأ في النظر إلى الصوت بمزيد من التفصيل. على سبيل المثال ، استخدام الجرأة القديمة (والمجانية) الجيدة . نفتح التسجيل الصوتي ونهتم بهيكله: بين ضغطات المفاتيح هناك صمت مطلق (كان شخصًا محظوظًا بظروف العمل ، ولم يكن لديك مكالمات هاتفية وزملاء الدردشة إلى الأبد!) ، مما يعني أنه لن يكون من الصعب استخراج كل ضغطة مفتاح عن طريق تصفية الأقسام مع اتساع إشارة الصفر.



حسنًا ، لنفعل ذلك. الآن لدينا شيئان: "صفيف" حيث يوجد 100500 نقرة ، والأمل في أن هذه الأصوات مكررة - عندها فقط يمكن القول "تم الضغط على المفتاح X مرات N ، والمفتاح Y كان M مرات". لذا ، تم تحليل جميع البيانات الأولية ، يبقى الإجابة على السؤال "ما الذي ستقودنا إليه مجموعة البيانات هذه ، شريطة أن يستمر التسجيل الصوتي لمدة 10 دقائق؟". نعم ، هذا صحيح ، لقد حان الوقت لكشف تحليل التردد الكلاسيكي . حسنًا ، نحن نختبر نظريتنا باستخدام python و numpy و scikits.audiolab (لمعالجة الصوت ، يمكنك اختيار أي حزمة أخرى وحتى اللغة بنفس النجاح).
لإعداد البيئة ، يمكنك تشغيل الأوامر التالية (يعمل بالتأكيد على Ubuntu 19.10):

$ sudo apt-get install -y python python-dev python-pip python-setuptools libsndfile-dev python-numpy
$ pip install --upgrade pip
$ pip install scikits.audiolab


ننفذ الآن اختبار افتراضنا في عدة أسطر من التعليمات البرمجية التي تستخدم الطريقة الأكثر بدائية لتحديد صوت النقر - من خلال مجموع قيم الصفيف المطابق المطابق:

get list of separated ‘clicks’
data, fs, enc = scikits.audiolab.wavread(filename)
data = data.ravel()
clicks = [list(g) for k, g in groupby(data, lambda x: x != 0) if k]

# calculate number of unique ‘clicks’ and their frequences
freqs = dict() 
cypher_test = list()
for click in clicks:
    value = np.sum(np.array(click), dtype = np.float32)
    cypher_test.append(value)
    if value not in freqs:
        freqs[value] = 1
    else:
        freqs[value] += 1


نتيجة تنفيذ الشفرة ، الموضحة في الرسم التخطيطي - مثل حرارة النيران في منتصف فصل الشتاء النووي - لا يمكن إلا أن تدفئ الروح: ما لا يقل عن 27 نقرة فريدة ، وحتى ظهور التوزيع يبعث على الثقة في أن تحليل التردد لن يكون عديم الجدوى.



وفقًا لويكيبيديا ومصادر أخرى أكثر موثوقية ، فإن 26 حرفًا من اللغة الإنجليزية ، مصنفة بترتيب تنازلي للحدوث ، تشكل سلسلة etaoinshrdlcumwfgypbvkjxqz . بالإضافة إلى ذلك ، بالطبع ، فجوة تحتل مكانة رائدة. أنت تعرف ماذا تفعل! مرة أخرى ، نستخدم عدة أسطر من الشفرة البدائية لمقارنة كل صوت عن طريق النقر على حرفه (في تكرار حدوثه) وتنفيذ الاستبدال الأولي:

COMMON_FREQ_ALPHABET = { 0:' ', 1:'e', 2:'t', 3:'a', 4:'o', 5:'i', 6:'n', 7:'s', 8:'h', 9:'r', 10:'d', 11:'l', 12:'c', 13:'u', 14:'m',15:'w', 16:'f', 17:'g', 18:'y', 19:'p', 20:'b', 21:'v', 22:'k', 23:'j', 24:'x', 25:'q', 26:'z' }

# calculate key
key = dict()
index = 0
for freq in sorted(freqs.items(), key=operator.itemgetter(1),reverse=True):
    key[freq[0]] = COMMON_FREQ_ALPHABET[index]
    index +=1

# replace sounds according the key
partly_plain_text = ""
for elem in cypher_test:
	partly_plain_text += key[elem]


بعد استبدال تحليل التردد ، نحصل على النص التالي:

onlineayvinf saty stw vltn selg kird moaher csctl ncmertl we tnswer utn metscre gtll saory retl enocfh worb ltrfe tvvetr tftin vltue scn satra zero gtua t gew rotd sveuitl vroklem etsa ketcay idet who lef ipere saone retuh vrodcua uca fipe reuord scre aoob jcesaion oca dcrinf vtss dry ahen show low lisa kltub okxeuas low lifha old frow wtauh aowtrd suhool my frow well heta norah mile mcsa resa tdd tmonf yocnf kesa kird beev kird gooa smtll wts bnow oca utme uca vltna some when bnow awo how dripe tftin vca while oaher some ocr letrn satr mincae digger men scrgtues infor retd hetrd lisa rtin utll vora yes whta idet ftme bind new him old deev eta keftn keftn or socah ahe some mtv tkle sonf i metn saory yetr fold mile dtrb eqtmvle world gish tfe geel ahocstnd one mile his ky ahe tkope ahose uhildren rtin gcll gtll tnimtl ury vocnd vltue ahose shora jciub where ahocfh saood fopern sorry i gorfoa i vromised ao lend yoc my uode fea ia grom my fiahck neoscveruoder htnd ahese binf wind utrb new vossikle tdd grom saood lifha down lipe mincae rotd foa satra gire ahocfh ahose some scn aia iaeai aet iaeai aia iaeai aet iaeai aia iaeai aet iaeai aia iaeai aet iaeai aia iaeai aet iaeai aia iaeai aet iaeai ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa ucn shoa shtbe wtpe ltke nibe shtbe wtpe ltke nibe shtbe wtpe ltke nibe shtbe wtpe ltke nibe shtbe wtpe ltke nibe shtbe wtpe htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn mtd dou htn dou gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe yet gipe

يبدو وكأنه شيء ذو مغزى ، ولكن يتم تخمين الكلمات الفردية بالتأكيد. ابحث بالتتابع عن الكلمات التي يكون من الواضح فيها أي بديل يجب إجراؤه:
  1. moaher -> الأم و التنوير -> الجواب ، أي يجب أن يتبادل a و t ؛
  2. larfe → كبير و selg → self ، أي يجب أن يكون f و g متبادلين ؛
  3. kird → طائر ، أي يتم استبدال k بـ b و onlinetyving → onlinetyping ، أي v استبدال ب p ؛
  4. Meascre → قياس و enocgh → يكفي ، أي يجب أن يكون u و c متبادلين.

نتيجة لهذه التلاعبات ، يتم تحويل النص بشكل كبير ، وتوضح كلمته الأولى نقص الاتصال: تم تسجيل التسجيل الصوتي أثناء ممارسة الطباعة على محاكاة لوحة المفاتيح. إيه ، مالك المفتاح كان من الواضح أنه لم يكن يستعد لنهاية العالم! .. يمكننا أن نكون سعداء بالنسبة له ، ربما هو الآن يتجه بسرعة كبيرة ، وهو يمزق الثلج الذي منع الخروج من ملجأه. لكن ما هذا لنا؟ سنلقي نظرة على النص ، ربما لا يزال هناك شيء مفيد.

onlinetyping stay saw plan self bird mother usual numeral we answer can measure fall story real enough worb large appear again place sun start zero fact a few road special problem east beauty idea who leg ipere stone reach product cut gipe record sure toob juestion out during pass dry then show low list blacb obxects low light old grow watch toward school my grow well heat north mile must rest add among young best bird beep bird foot small was bnow out came cut plant some when bnow two how dripe again put while other some our learn star minute differ men surfaces ingor read heard list rain call port yes what idea game bind new him old deep eat began began or south the some map able song i mean story year gold mile darb eqample world fish age feel thousand one mile his by the abope those children rain full fall animal cry pound place those short juicb where though stood gopern sorry i forgot i promised to lend you my code get it from my github neosupercoder hand these bing wind carb new possible add from stood light down lipe minute road got start fire though those some sun tit iteti tea iteti tit iteti tea iteti tit iteti tea iteti tit iteti tea iteti tit iteti tea iteti tit iteti tea iteti cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot cun shot shabe wape labe nibe shabe wape labe nibe shabe wape labe nibe shabe wape labe nibe shabe wape labe nibe shabe wape han mad doc han mad doc han mad doc han mad doc han mad doc han mad doc han mad doc han mad doc han mad doc han doc fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe yea fipe

يبدو أننا كنا محظوظين: أثناء التدريب ، كان شخص ما مشتتًا وكتب رسالة إنقاذ إلى صديقه ، ربما في بعض الرسائل: عذرًا ، نسيت أنني وعدت بإعطائك الكود الخاص بي ليحصل عليه من بلدي الجديد.. بطبيعة الحال ، قراءة مراسلات شخص آخر ليست جيدة ، ولكن هناك استثناء بنسبة مائة بالمائة ، لقد دفعنا أكثر مما يكفي لهذه المعلومات. نذهب إلى github ونبحث عن المستودع باسم المستخدم:



Success! يبقى فقط لقراءة الملف الوحيد من مستودع "الطب الجديد":



مرحى! الآن نحن أصحاب المفتاح السعداء!
للأمام - تحليل المهام الأخرى NeoQUEST-2020 - لن نسمح لقرائنا بالملل من العزلة الذاتية!

All Articles