Jump to content
¯\_( ツ)_/¯
  • TAD GROUP are currently hiring penetration testers. Please read the topic in Career Central subforum.
  • Sponsored Ad
ТУК НЕ СЕ ПРЕДЛАГАТ ХАКЕРСКИ УСЛУГИ ! ×

Avatara

Moderators
  • Content Count

    427
  • Joined

  • Last visited

  • Days Won

    91

Avatara last won the day on August 11

Avatara had the most liked content!

Community Reputation

252 Excellent

About Avatara

  • Rank
    Advanced

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Здравейте, Искам да Ви представя едно приложение на нашата колежка Ирен Пенчева. Държа да подчертая, че тя е сравнително "млад" програмист (визирам стаж в приложното и системно програмиране, а не практически опит). Приложението се нарича Web Tools и е ориентирано към web-разработчици, както и към тези, които са просто любопитни и изучават процесите в мрежата. Това, което е забавно е наличието на Micro Web Server (MWS), с помощтта на който може незабавно да тествате HTML5 проект, а ако разполагате със статичен IP адрес, да правите много повече неща. Също така има и вграден FTP клиент (тук аз имам доста забележки, но все пак е само начало), който се обновява. В момента е по-старата версия. Надявам се скоро да бъде включена най-новата такава. В примерите са включени проекти за мултимедиа (аудио и видео възпроизвеждане), както и други HTML5 шаблони. Ще Ви бъда благодарен за всяка една препоръка (колежката също). Към момента продукта се разпространява напълно безплатно за Windows 10. ОФИЦИАЛЕН АДРЕС: https://www.microsoft.com/store/apps/9P0HPCTKXRGZ И малко визуална информация ... И с разрешение на колежката, няколко изображения от новият FTP Client, който ще бъде интегриран в приложението. Има специализирани решения за възпроизвеждане на мултимедиа и не само, което отсъства във версията вйкючена в Web Tools. Моля Ви да имате в предвид, че все пак това е първият самостоятелен проект на колежката ни. До момента тя е работила само и единствено като член на екип, но не я щадете. Има много неща, които (според мен) трябва да бъдат коригирани, но много държа да чуя и вашето мнение. Забележка: Дизайнът е съобразен с тенденциите на Black Screen, но е възможно скоро да бъде радикално изменен.
  2. И малко от "кухнята" ... Как изглеждат някои от модулите за Android (в момента се тестват за апартна съвместимост). Забележка: Търговското наименование ще бъде Net One, но няма да се разпространява през Google Play. Мисля, че е излишно да споменавам, че след като го има за Android го има и за Linux.
  3. Още веднъж благодарности. В момента има нова тестова версия на продукта, както и закрита за потребители версия за Android (мобилно приложение, с вградем крипто месенджър). ТЕСТОВА ВЕРСИЯ ЗА WINDOWS 10 https://www.microsoft.com/store/apps/9P5SXJ8BL4GM Разширен набор от криптопримитиви, добавен модул System Protection и много допълнения. За тези, които имат слабост към работата на конзола ... Ако някой иска лиценз, нека ми изпрати съобщение на лични, за да мога да му върна Promo Key за безплатна активация.
  4. Моето мнение за т.н. "криптовалута" (както и за Open SSL, TLS, RSA и др.) се различава диаметрално от масово битуващото, поради следните прости причини: 1. Всички масово използвани методи за шифроване (обърнете внимание, че визирам "шифроване", а не "криптиране", защото има разлика) са квантовоуязвими. 2. При всички стандартни методи на шифроване имате наложени правни ограничения (най-вече в дължината на ключа). 3. Всички познати методи използват сума по модул две (изключващо или - XOR) за побитовите операции. Мога да продължа да изброявам, но не искам да влизам в конфликт с никого. Истината обаче е, че шифровъчни криптопримитиви, които се ползват работят с цели числа. При това не с всякакви цели числа, а с ограничено множество. Самият процес на "копаене" винаги ужасно ме е забавлявал. Що се отнася до "отговора" на задачата мисля, че някой е публикувал решение.
  5. Подписването не само е задължително, но и има изискване използваните сертификати да са одобрени от Microsoft. Самата идея да се скрие процес е доста абсурдна, с оглед на наличието на прекрасно работещи приложения за контрол на процесите. Реално шприложението не само, ще бъде прихванато, но и може да бъде всячески манипулирано или дори премахнато. Ако обаче е с учебна цел или е нужно да се направи система за конфигуриране на локални мрежи (което е допустимо и дори се насърчава при корпоративните решения), тогава бняма проблем.
  6. Контролни въпроси: 1. Каква е разликата между шифроване с два ключа и асиметрично шифроване? 2. Какво представлява цифровият контейнер? 3. Има ли разлика между "парола" и "секретен ключ"? 4. Kакво точно означава числото 2048 след RSA (RSA - 2048)? 5. Каква е разликата между проста замяна и шифроване със секретен ключ? 6. Колко са страните, осъществяващи контрол, в случай на обмен на криптирани данни? 7. Къде е слабото място на съвременните системи за шифроване и каква е връзката му с факторизацията? 8. Каква е разликата между натурални и прости числа? 9. Какво е "канонично разлагане на прости множители"? Опитайте се сами да отговорите на тези прости въпроси.
  7. И така. Както вече казахме факторизацията играе основна роля в масово използваните системи за криптиране. Проблемът с факторизацията на числата не е възникнал вчера. Той съществува от хиляди години. Можем само да гадаем защо през 1900 г. на Математическия конгрес Д. Хилберт не включва факторизацията сред математическите приоритети. И до днес тя не е в списъка на нерешените математически проблеми на С. Улам. Специалното внимание и интерес на математиците към проблема се появи едва през последните десетилетия. Основната причина за това е откриването на криптографски механизъм, използващ два ключа (обърнете внимание, че ползвам термина "два ключа", а не "асиметрично шифроване"). Предполагам, че днешният интерес към проблема с факторизацията на числата е продиктуван от известна несигурност по отношение на теоретичната обосновка на устойчивостта срещу разкриване на двуцифрения RSA алгоритъм, който масово се използва днес. Истината е, че този шифър може да бъде разбит, без да е нужно да познаваме частния (private) ключ, а само познавайки публичния (public) ключ. Този процес е познат като "дешифриране без ключ". Към момента в теорията за алгебраичните пръстени все още не са намерени необходимите методи за практическата реализация. Това се дължи на факта, че липсва достатъчно надеждна операция, обратна на умножението на числата. Едно просто бързо и достъпно мултипликативно разлагане на съставни числа може да се превърне в такава аритметична операция и ще попълни арсенала от изчислителни инструменти в математиката и в криптоанализа. Въпреки гореизложеното ние бихме могли да разберем как точно функционира RSA, както и всички други криптосистеми, използващи прости числа. Защо е нужно да се занимаваме с този въпрос? Ако ми позволите, ще ви предоставя чисто финансов аргумент. През месец април на далечната 1991 година количеството прости числа в RSA е 100 (от там RSA-100). Тогава информацията за тези числа е безплатна. От 3 декември 2003 година, с появата на RSA-572 (брой прости множители - 576) изискуемата сума за достъп до информацията е 10 000 USD (десет хиляди щатски долара). Към днешна дата за достъп до простите множители на RSA-2048 сумата е нараснала на "скромните" 200 000 USD (двеста хиляди щатски долара). Както сами може да се убедите от факторизацията се печелят стотици милиона годишно. И обърнете внимание ... Все още говорим за факторизация, а не за криптиращи системи. Ако обаче някой успее да направи "безключов дешифратор", гарантирам, че само за няколко месеца ще бъде най-богатия човек в света. Повярвайте това не е чак толкова трудно (ако можете да четете на латински и успеете да намерите първите издания на трудовете на Ойлер и Нютон в някой антикварен магазин). Ако някой ви каже, че квантовите компютри, паралелните изчисления и др. ще разрешат проблема бъдете убедени, че лъже. Не. Проблемът няма да бъде решен. Ще стане много по-скъп, но решение няма да има, защото фундаменталната основа е изначално сбъркана. За разлика от много съвременни автори (не само тези, които пишат по форуми, като мен, но и такива, които издават учебни помагала) нито Нютон, нито Ойлер са използвали фразата: "от тук без проблем получаваме ... ", или "както се вижда не представлява проблем да получим ...". Уважаеми колеги, дори на математик като Лаплас му се е наложило да се бори със сложни математически уравнения с месеци за да разбере как точно се получава крайния резултат на нещо, което би следвало да се получи "много лесно и без проблеми". Истината е, че е проблем и то сериозен. Не е важно аз какво знам. Важно е какво ще разберете вие, защото и до днес много често срещам твърдения, че 2048 при RSA-2048 е брой битове. Ако отново прочетете внимателно написаното по-горе ще разберете, че става дума за прости числа, а не за битове. Разликата е фундаментална. След така направеното занимателно отклонение да се върнем към практиката, която е суров учител. Съществуват няколко метода, но ние ще разгледаме само основните, поради ограниченият обем на този курс (а и този раздел не е част от курса о криптография, а е по-скоро спомагателен модул). ПОСЛЕДОВАТЕЛНО ОБХОЖДАНЕ НА ВСИЧКИ ВЪЗМОЖНИ ДЕЛИТЕЛИ (метод на грубата сила) I. НАИВНА РЕАЛИЗАЦИЯ - О(n) Определение Алгоритъм за факторизиране или тестване простотата на число, посредством последователно търсене на всички възможни потенциални делители. Казано с прости думи в този случай ще се опитаме да намерим всички числа, на които дадено число се дели без остатък като започнем от 1 и стигнем до ... Тук вече е трудно. Реално можем да кажем, че ще стигнем до 10 000 или 100 000, но може да продължим с много по-големи числа. Практическата реализация е много проста. Избираме си едно произволно число, например 658 и започваме да го делим: 658 / 1 = 658 - дели се без остатък. 1 е първият прост делител. 656 / 2 = 328 - дели се без остатък. 2 е вторият прост делител, но числото 2 не е равно на 658 следователно 658 не е просто число. Няма нужда да продължаваме. В общи линии така може да тестваме всяко едно цяло положително число. Едва ли ще повярвате, че това е свързано с основен принцип в математиката, който се изучава още в началното училище. Според този принцпип всяко натурално число N > 1 може да бъде представено като произведение от прости числа N = p1 x p2 x p3 x ... x pk N = Пpi = p1 x p2 x … x pj−1 x pj x pj+1 x ... x pk където: p1, p2 , p3, ... , pk са прости числа. Този начин на представяне на числото N се нарича "КАНОНИЧНО РАЗЛАГАНЕ НА ПРОСТИ МНОЖИТЕЛИ". Пример: p1 = 1 p2 = 2 p3 = 3 N = 6, k = 3 N = Пpi = p1 x p2 x pk = p1 x p2 x p3 = 1 x 2 x 3 = 6 Пример: Натурални числа (от латинската дума naturalis - естествен, натурален), са числата, които използваме за броене. Едно, две, три, четири, пет и т.н. Множеството на натуралните числа се означава с латинската буква N. Според ISO 31-11 (1992 год) и ISO 80000-2 (2009 год) съществуват следните множества натурални числа: N - Множество на натуралните числа, включващо 0 - { 0, 1, 2, 3, 4, 5 ... } N* - Множество на натуралните числа без нула - { 1, 2, 3, 4, 5 ... } Забележка: Различията между N и N* са изключително важни ( визитам използването на 0 ) при избор на програмен език. Спомнете си как се обработват масивите в C, C++, Java, Pyton и др. и как това се прави във FORTRAN, Pascal, Object pascal, delphi, ADA, Prolog и др.. 2, 3, 7, ..., 11, 13, 17, ... ОПРЕДЕЛЕНИЕ Просто число ще нричаме натурално число по-голямо от единица, което има само два цели положителни делителя, а именно 1 и самото себе си. Пример: Числата 2, 3, 7, ..., 11, 13, 17, ... са прости. Следващата стъпка е да рзпишем алгоритъма, който би ни позволил да разложим едно натурално число на прости множители. За да направим това ще използваме основният принцип (или теорема, защото всее пак подлежи на доказване) в математиката за действия с натурални числа. В случая, алгоритъма може да бъде записан във вида: ∀ x,y ∈ N x < y ⟹ ( x/y < 1 ) Съгласете се, че определено изглежда доста объркващо. Нека сега се опитаме да го разчетем. Написаното звучи така: За всяка двойка натурални числа X и Y, за които е в сила неравенството X < Y ( ∀ x,y ∈ N x < y ), следва неравенство X/Y < 1. Пример: Нека имаме следната двойка натурални числа: X = 3 ; Y = 5 Очевидно е, че X < Y тъй като 3 < 5. От тук може да запишем: X/Y = 3/5 = 0,6 < 1 Сами може да се убедите, че теоремата е в сила. На практика ние получихме първото и най-важно ограничително условие за нашият алгоритъм. Когато извършваме факторизация ние ще започваме от 2 и ще продължим до числото, за което правим проверка. Пример: Нека извършим факторизация на числото 7. С оглед на гореизложеното започваме в следната последователност: 7 mod 2 = 3 - Защото 7/2 = 3,5 > 0 - изключваме 2 7 mod 3 = 2 - Защото 7/3 = 2,33333333... > 0 - изключваме 3 7 mod 4 = 1 - Защото 7/4 = 1,75 > 0 - изключваме 4 7 mod 5 = 1 - Защото 7/5 = 1,4 > 0 - изключваме 5 7 mod 6 = 1 - Защото 1,1666666... > 0 изключваме 6 7 mod 7 = 0 - Za]oto 7/7 = 1 и няма нищо след десетичната запетая. Това означава, че ще добавим 7 към списъка с прости делители. Тъй като списъка имаме само две числа { 1, 7 } числото 7 е просто. Забележка: В информатиката mod е математическа функция, която връща като резултат остатъка от деление на X на Y ( остатъка от X/Y ) ВАЖНО В криптоанализа е прието описанието на алгоритмите да се извършва в псевдокод. Държа да подчертая, че псевдокодовете не са програмни езици и те служат за да има яснота какво се прави и в каква последователност. Поради недостатъчно познаване на материята много често се счита, че псевдокодовете са pascal. Това категорично не е вярно и разликите са повече от очевидни. Описанието на алгоритъма в псевдокод изглежда така: function getMultipliers (number: int): vector<int> // В result ще се записват получените множители ... result = vector<int> // Това е числото, чиито множители трябва да търсим (делимото) ... curNum = number // Това е числото, на което делим (делителят) ... probe = 2 while curNum ≠ 1 if curNum mod probe ≠ 0 // Проверяваме всички възможни множители [2; probe] probe++ else // Делим до тогава, докато това е възможно .... curNum /= probe result += [probe] return result И алгоритъма на функцията за намиране на простите делители (в псевдокод) function getDividers(number: int): vector<int> // Получаване на масива на делителите ... result = vector<int> // Проверяваме последователно всеки един потенциален делител ... for probe = 2 to number if number mod probe = 0 // Целочислено делене на probe на number ... result += [probe] return result Това е за днес. Числата, не са нещо толкова елементарно, колкото сме свикнали да мислим. Никога не забравяйте, че в цифровите решения, информацията се записва под формата на цели положителни числа, с всички произтичащи от това последствия.
  8. Колкото и абсурдно да звучи за някои, шифроването посредством проста замяна е използвано до средата на XX век. Предполагам, че мнозина са чиували за Енигма. При нея се използват механично електрически схеми за извършване на проста замяна. За разлика от Енигма (която е била успешно разбита), руската Феялка (използвана до началото на 70-те години на миналия век) остава една от най-устойчивите криптографски машини, използващи метода на проста замяна до днес. Причините за това са по-скоро лингвистични и определено имат малко общо с математиката. Но технологиите са се развивали и с появата на компютрите и цифровите системи се е наложило да бъдат потърсени нови решения. Следващата тема е свързана със съвременните комуникации. Ще се наложи да си припомним математиката от 6-ти клас, както и да поговорим защо точно тя е основополагаща на всичко, което в момента се счита за актуално в света на криптографията. Прости числа, разлагане на прости множители и факторизация По дефиниция под "просто число" ще разбираме натурално (цяло, положително) число, което има само два различни натурални (цели, положителни) делители, а именно единица и самото число. Как да си обясним това? Простите числа се делят без остатък само и единствено на самите себе си и на единица. Пример: 1, 3, 5 … 3/3 = 1 3/1 = 3 5/5 = 1 5/1 = 5 Но числата 4 и 6 (примерно) не са прости защото: 4/1 = 4 4/2 = 2 4/4 = 1 6/1 = 6 6/2 = 3 6/3 = 2 6/6 = 1 Следващата стъпка е да се научим да разделяме всяко число на прости множители. Ако числата са малки то това е много лесно. Пример: Числото 6 може да бъде представено като 2x3 ( 6 = 2x3 ) Числото 21 може да бъде представено като 7x3 ( 7 = 7x3 ) Числото 323 може да бъде представено като 17x19 ( 323 = 17x19 ) Обърнете внимание на факта, че 2, 3, 7, 17 и 19 са прости числа. Именно посредством произведението на тези прости числа ние представяме числата 6, 21 и 323, които не са прости. Ако обаче положите усилия ще установите, че не е толкова лесно да разложите на прости множители числото 323. А сега си представете, че трябва да разложитее н прости множители следното число: 123234234234234903458349094764897538423483120342038120381280123812038120381231231928308013485897595893475893459347593475934573298457392475932134756465834535345907856348452312312310929004534590345394593405906406840868564564566434564656745745785685685686587956464561234345356567909098 Това ще се окаже доста трудно дори ако използвате суперкомпютър. Шифроване с частен (private) и публичен (public) ключ Често ще срещате термини като „симетрично” и „асиметрично” шифроване. Прието е под „асиметрично” да се разбира процес, при който се използват два секретни ключа (публичен – наричан още „открит” и частем, наричан още „секретен”). Лично аз приемам подобно определение, макар обективно погледнато то да не е коректно от гледна точка на математическата логика и не само. Истината е, че то е наложено от използваната англоезична терминология, но това често е водело до доста весели недоразумения. И така нека се запознаем с асиметричните методи на шифроване, които днес са толкова актуални и се използват масово в internet. Нека двама души, намиращи се в различни държави да желаят да обменят зашифровани съобщения. Ако те са се разбрали предварително и двамата използват една и съща парола ще имаме шифроване с частен ключ (private) или "симетрично шифроване" (което от моя гледна точка е неправилно и като термин и като дефиниция, но това е друга тема) Фиг.1. Шифроване с един секретен ключ. Друг вариан е ако имаме един контейнер, който може да се заключи с един ключ (зеления ключ), но да бъде отворен с друг ключ (синият ключ). В този случай подателят зашифрова съобщението, като използва зеленият ключ, а получателят (реципиента) го дешифрира като използва зеленият ключ. Фиг.2. Шифроване с повече от един секретен ключ. Но да допуснем, че подателят и получателят никога не са се виждали и не са в състояние да определят начина, по който ще обменят секретните ключове. В този случай подателят изпраща на получателя празен контейнер, за който само той има ключ (зеления ключ). Получателят поставя съобщението в контейнера и го затваря, след което само притежятелят на зеления ключ може да отвори контейнера. Получателят връща заключения контейнер (в който се съхранява съобщението) на подателя, който посредством зеления ключ отваря контейнера и прочита съобщението. Фиг.3. Модел на асиметрично шифроване без наличие на трета страна (удостверител), гарантираща целостта и достоверността на съобщението. Каква е връзката с простите числа в този случай? Колкото и абсурдно да прозвучи за някой един от основните въпроси е как да определим дали едно голямо число е просто. Тук опираме до теорема на Ферма, теорема на Лагранж и науки, познати ни като теоретично числови криптографски методи, модулна аритметика и др.. Както вече споменахме празният контейнер представлява много голямо число (колкото по-голямо, толкова по-добре), които може да бъде представено като произведение на прости числа. Процесът на разлагане на едно число на прости множители се нарича "факторизация". Факторизацията е изислително сложна задача. Към момента няма доказателства за съществуването на ефективен не-квантов метод, който да може ни позволи да се справм с факторизаията на големи числа. Също така не съществува и метод, който да ни позволи да направим това с по-малки числа в приемлив период от време (полиноминално време). Факторизацията е основата, върху която се гради съвременната криптография. Тя се прилага при елиптичните криви, алгебричната теория на числата и при квантовите изчисления. Алгоритъмът RCA, посредством който се реализират криптографски приложения като PGP, S/MIME, TLS/SSL, IPSEC/IKE и др., използва факторизация (разлагане на прости множители). Как точно се реализира това на практика и каква е връзката с математиката ще видим в следващите раздели.
  9. Следващата форма на шифроване, която ще разгледаме е т.н. "непосредствена замяна" или "шифър на простата замяна". При този начин на шифроване всяка буква от използваната азбука (всеки символ) се заменя с друг символ. Фиг.1. Шифроване посредством проста замяна. На фиг.1. е показана класическа форма на шифроване посредством проста замяна. Както може да се види, всяка буква от азбуката се заменя със символ, който няма непосредствена връзка с азбуката. В този случай ние нямаме "отместване", а имаме именно замяна. В най-простия случай може да заменим една буква с друга буква от азбуката, Пример: Ако извършваме замяна на една буква от българската азбука с друга буква от българската азбука ще получим следното: А:= Щ Б:= Ъ В:= Я Г:= Ю . . . Ю:= С Я:= Д Ако отново се обърнем към математиката ще видим, че възможните комбинации в този случай са 30! (трудесет фактурел), където 30 е броят на буквите в българската азбука. На практика броят на възможните комбинации P се изчислява по формулата: P = N! = 30! = 1x2x3x4x5x6x7x8x9 ... x28x29x30 = 265 252 859 812 191 000 000 000 000 000 000 Забележка: E +32 означава 10 на степен 32. Както сами може да се убедите това е едно доста голямо число. Ако се опитате с помощта на молив и лист да извършите дешифриране, това ще бъде невъзможно. Причината е, че ще отнеме толкова много време, че ще обезмисли процеса на дешифриране. Как бихме могли да се справим с този проблем? На помощ идва математиката и в частност т.н. "честотен анализ". Какво е честотен анализ и как с негова помощ ще бъдем в състояние да обезмислим шифроването посредством проста замяна? Истината е, че всяка буква се използва различен брой пъти. Без значение какъв е текста на един език, гласните и съгласните се използват различен брой пъти. Това се нарича честота на използване и е основа на наука, известна като "приложна лингвистика. Например вероятността буквата А да се срещне в текст на български език е много по-голяма от тази да се срещне буквата Г. А - 11,60 Б - 1,65 В - 4,71 Г - 1,19 Д - 3,11 Е - 9,2 . . . Ю - 0,11 Я - 1,86 Честотата на буквата А е равна на 11,60, докато на буквата Г е само 1,19. Ако ние имаме един достатъчно голям текст е достатъчно да изброим повтарящите се в текста символи. Ако честотата на повторение на буквата Щ е равна на 11,60, очевидно е, че това е символа, който е заменил буквата А. Това важи с пълна сила, ако използваме произволен символ, така както е показано на Фиг.2. Фиг.2. Определяне съответствие въз основа на честотата на срещане в текста. На практика въз основа на честотата, с ковто един символ се среща в текста и разполагайки с информация за честотното разпределение на буквите за всеки един език ние с лекота можем да дешифрираме всеки един текст. Всичко това е възможно, благодарение на една проста формула, в която се използва деление, което сме изучавали в средния курс на обучение. За да разберем каква е честотат, с ковто една или друга буква се среща е нужно просто да разделим точният брой на използването на една буква в конкретен текст, разделено на общият брой на използване на буквите в текста. Много интересна е историята на определяне на честотата за българските букви. Тук трябва да отдадем дължимото на г-н Б.Пенков и неговите колеги, които през 1962 година подлагат на анализ откъс от романа "Под игото" на Иван Вазов, издание 1894 година. Важно е, че в тези изследвания те не са използвали само и единствено статистически и лингвистични методи, но също така успешно са приложили и базови принципи на ергономията. Горещо препоръчам и статията на Б. Стефанов и В. Бирданова, публикувана в сп. "Computer", 1997, 2, 56-62. В тази статия има много пунктове, които са базови в съвременния криптоанализ. Също така този подход е фундаментален принцип в компютърната лингвистика (computational linguistics). Там не се използват абстрактн модели, а чисто приложни методи. Темата е сложна и излиза извън предмета на настоящите разглеждания, но предполагам, че вече добивате някаква представа, какъв е обхвата на материята, която разглеждаме.
  10. Сега ако ми позволите ще извърша малко отклонение от темата. То е важно за всички онези, които не са изучавали четири или повече семестъра висша математика. Ще започнем с прости примери, като постепенно навлизаме във все по-сериозна материя. Важно е да разберем базовите принципи и какви са техните слаби места. МАТЕМАТИКА И КРИПТОГРАФИЯ (спомагателен раздел) Защо трябва да знаем какво представляват простите числа, какво е функция на Ойлер, какво са логаритмите и много други неща от гледна точка на криптографията. Целта на този урок е да ни позволи да изградим практически умения за използване на математическите модели в процеса на криптоанализ. Това е от изключително значение за последващите разглеждания и значително би облекчило цялостното разбиране на една много сложна материя. И така ... За какво служи висшата математика и къде се използва? Колкото и абсурдно да впрозвучи за мнозина, всеки път когато изпращате SMS или просто провеждате разговор, с помощта на мобилния си телефон, вие използвате висша математика. Това е неизбежно. Съгласете се, че всеки би желал да може да проведе разговор, да изпрати електронно съобщение без някой друг, който не е оторизиран за това да го прихване и използва за користни цели. Още по лошо е ако телефонът ни бъде откраднат, а вътре се съдържа информация, в т.ч. и свързана с електронни разплащания, която бихме желали да остане конфеденциална. На практика ние не можем лесно да променяме апаратните устройства, които оизползваме. Не всеки разполага с познания в области като микроелектроника или цифрова схемотехника. Това е „ограничение”, с което трябва да се съобразяваме. Това, което ни остава е да използваме лесни за реализация методи, които може да бъдат използвани не само при електронни устройства. Един от най-старите, познати към момента методи е т.н. шифър на Цезар. Как изглежда той? Пример: Нека имаме азбуката ( в нашият случай това е българската азбука, която добре познаваме ) АБВГДЕЖЗИЙКЛМНОПРСТУФXЦЧШЩЪЬ ЮЯ както и цифрите 1234567890 Нека имаме съобщение от вида: ДА СЕ СРЕЩНЕМ В 10 ЧАСА В този случай всяка буква в азбуката се заменя с буква (или цифра), която се намира в определен брой позиции в ляво. Нека изберем, че отместването ще бъде на две позиции. Тогава ще имаме следните съответствия: A:= B; Б:= Г; В:= Д и т.н., а Ю:= А а Я:= Б Аналогично за цифрите: 1:= 3; 2:= 4; 3:= 5 и т.н. а 9:= 1 а 0:= 2 Прилагайки шифъра на Цезар ще имаме следното шифровано съобщение: ЖВ УЗ УТЮПО Д 32 ЩВУВ Сами може да се убедите, че ако не познавате принципа на разместване, горният текст изглежда напълно безмислен. Ако обаче познавате принципа, да се извърши обратното преобрзуване (разшифроването на текста) не би представлявало проблем. Дори да не знаете на колко единици е извършено отместването, то няма да отнеме кой знае колко време ако тествате през единица до получаване на смислен текст. Каква е връзката с математиката? Не знам дали ви е направило впечатление, че умишлено съм използвал ":=" за да покажа как се реализира замяната. В този случай използвам математическият символ за присвояване (равно по дефиниция или равно по определение). Искам да обърна внимание, че това не е "=", а е нещо различно, от математическа (логическа и системна) гледна точка. x:= y или ако X e буквата "В" то тогава Y ще бъде буквата "Д" или В:= Д ( В по определение е Д ), означава, че ако срещнем в текста X ние ще трябва да запишем Y (ако буквата е "В" то тя трябва по дефиниция да бъде заменена с буквата "Д") или ако трябва да изразим това програмно: if X = 'В' then begin Y:= 'Д' ; X:= Y ; end; или записано в оптимизиран вид: if X = 'В' then X:= 'Д' ; ако i-тият символ в изречението е буквата В, тогава вместо В трябва да се запише буквата Д. ВАЖНО! Никога не бива да се бърка равенство с "равно по дефиниция" (равно по определение) защото това са различни неща. Има и още един важен момент. В математиката има термини като "вектор" и "индексирана променлива", а в програмирането термин "едномерен масив". Нека запишем буквите в азбуката, като след всяка една в скоби поставим нейния пореден номер. За буква А той е 1 (първа буква), за буква Б това е 2 (втора буква) и т.н. до буква Я, която е тридесетата буква в азбуката. А(1) Б(2) В(3) Г(4) Д(5) ... Ю(29) Я(30) нека сега напишем следното: Буква (1) Буква(2) Буква(3) Буква(4) Буква(5) .... Буква(29) Буква(30) Буква (1) е А, Буква (2) е Б, Буква (3) е В, Буква (4) е Г и т.н.. До тук няма нищо, което да не е разбираемо. Но сега внимавайте добре. ТЕЗА Всяка една азбука може да бъде разглеждана като вектор ред от математическа гледна точка. Всяка една буква е "индексирана променлива" от математическая гледна точка. Използвам термина "променлива, защото различните азбуки са с различна дължина и петата буква в българската азбука не е като петата буква в английската или в японската хирагана. Звучи страшно, но дали наистина е така? Обърнете внимание, че ние изписваме буквите като последователност от символи на един ... ред. Също така ние изписваме азбуката, като спазваме определена последователност (започвме от буквата А и завършваме с Я, т.е. буквите в азбуката следват определена последователност "посока"). Също така броят на буквите о ограничен. В случая те са 30 или ако с N означим броят на буквите в българската азбука то N ще бъде равно на 30 (N = 30). ДЕФИНИЦИЯ Вектор (от лат. vector, носител) — ще наричаме математически обект, който се характеризира с големина (стойност) и посока (направление). Както сами може да се убедите, българската азбука (а и всяка една азбука) напълно отговаря на математическата дефиниция за вектор. И понеже я изписваме на един хоризонтален ред, то ще казваме, че имаме "вектор ред"). От тук азбуката може да бъде представена във вида: { X1, X2, X3, X4, X5, ... , Xn } където: X1 = А, X2 = Б, X4 = В ... Xn = Я при n = N = 30; както виждате векторът е набор от N на брой елемента Xi - записан в стандартна форма { X1, X2, X3, X4, X5, ... , Xn }. Има и други начини за записване на векторите (във физиката и в математиката се изписват различно, като в математиката има поне три начина), но това е друга тема. Всеки един елемент има индекс i, който показва кой по ред е този елемент. В случая с българската азбука Xi = А, когато i = 1 (X1 = А), Xi = Б, когато i = 2 (X2 = Б), Xi = В, когато i = 2 (X3 = В) и т.н. до Xn = Я (последният елемент от групата), когато i = N (X30 = Я). В програмирането векторите са известни с термина "едномерни масиви". Записват се като X: Array [1..30] of Char; (набор от тридесет символа - X: Масив [1..30] от Букви); В този случай: X[1] = 'А', X[2] = 'Б', X[3] = 'В', X[4] = 'Г', X[5] = 'Д' ... , X[30] = 'Я' Съществуват и други форми на деклариране, в съответствие с използвания език за програмиране, но ... Нека ги погледнем обективно: char X[30] или char* X[30] (при C++) Забележка: Тук втората декларация е указател. Това не бива да се забравя. В Delphi има pChar, което е доста различно от гледна точка на машинното изпълнение. char[30] X (класически Java стил на деклариране на масив от символи) string[30] X е препоръчителен, но е доста сериозна тема защо и какви предимства, от гледна точка на криптографията предоставя. Тук имаме и още един момент, който рядко се отчита. При Java имате: char symbol = 'A'; но също така: char symbol = '\u0042'; Това също е много важно и ще бъде обсъждано на един по-късен етап, когато анализираме двоичния код в криптосистемите. Забележка: При Java по подразбиране се използва unicode. При Delphi имате AnsiChar, WideChar, Char, което не само е доста различно, но и е от определящо значение, когато става дума за приложна криптография. В този случай: X[1] = 'А', X[2] = 'Б', X[3] = 'В', X[4] = 'Г', X[5] = 'Д' ... , X[30] = 'Я' Забележка: Ето тук моята позиция е в конфликт с битуващото в internet мнение. Причината е в езиците за програмиране (Java, C, C++, Python и др.), чиито синтаксис е наследен от C. Там се използва знак за равенство "=", което от гледна точка на криптоанализа и математическата логика не е коректно. Обърнете внимание, че в момента разглеждаме най-елементарния шифър, вече установихме един от многото сериозни проблеми, на който не винаги се обръща внимяние. За масивите и начина на отчитане на елементите (при C, C++, Java, Python, Ruby и пр.) няма да коментирам, защото там началният елемент е с индекс 0 (нула), но има огромна разлика между математическа и компютърна нула, въпрос, на който ще отделим специално внимание и който често се пренебрегва. При програмните езици, съществува език наричан ALGOL, чиято задача е да се описват прецизно алгоритмите. Други програмни езици, които ни позволяват това са Object Pascal и Delphi, които освен всичко друго са апаратно и платформено независими (и за да няма глупави спорове по темата просто посетете следния адрес и се запознайте много внимателно с написаното и показаното там: https://www.embarcadero.com/products/delphi). Както вече споменах в началото на курса ние сме длъжни да се придържаме стриктно съм въведените стандарти и действащите нормативни разпоредби. Системите са криптиране са специфични програмни продукти, с всички произтичащи от това последствия. Моля ви да не ги бъркаме с електронни подписи и пр., а и тази тема вече е разгледана в първи раздел. ( следва продължение )
  11. КОНТРОЛНИ ВЪПРОСИ: 1. Опитайте се да изясните за себе си съществува ли разлика между шифроване и криптографска система? 2. Считате ли, че за да бъде шифровано едно съобщение е нужно да си използват всички познати криптографски примитиви? 3. Каква е разликата между електронен подпис и битова схема? 4. Какви са различията между разделянето на секрета и логическия контир, при гарантиране достъпа до информация? 5. Каква е разликата между "работещ фактор" и "метод на работа"? 6. От какво зависи ефективността на криптопримитивите? 7. Какво отличава комуникационните протоколи от тези на конфеденциалните изчисления? 8. Къде се използват логически функции и за какво? 9. Къде се използват математически изчисления и за какво? 10. Използването на силен шифровъчен алгоритъм гарантира ли конфеденциалността на данните? Опитайте се самои да отговорите на така поставените въпроси. Добре би било да потърсите допълнителна информация по темата. Целта на въпросите е да затвърдите знаничта и да получите увереност. Това би ви позволило лестно да се спраите с тестовете. Важно е да знаете, че темата за инициализиращите вектори, "посоляването" и др. са обект на детайлни разглеждания в следващите раздели, но не са обвързани с базовата терминология. Причината за това е, че те не се използват при всички криптосистеми и са по-скоро частни случаи. Въпреки това ще бъдат детайлно изучени, поради своята значимост и специфика на приложение.
  12. 6.1.2. Основни криптографски примитиви Основните стандартни криптографски примитиви са както следва: - Хеширане – Процес на преобразуване на масив от входни данни с произволна дължина в изходен битов низ с фиксирана дължина. Криптографският примитив се нарича хеш-функция, а полученият резултат се наричат хеш код, контролна сума или дайджест на съобщението (message digest). Резултатите от хеширането би следвало да бъдат уникални, от статистическа гледна точка. Ако имаме входни данни, различаващи се само с един единствен байт получените резултати ще бъдат различни. - Криптиране със симетричен ключ – Процес, при който и двете страни, участващи в обмена на данни, използват абсолютно еднакви ключове за криптиране и декриптиране на данни. - Асиметрично криптиране – Процес, при който се използват два различни ключа. Прието е единият ключ да се нарича публичен, а другият - секретен. При асиметричното криптиране е необходимо да се използват и двата ключа. Ако данните са криптирани с публичен ключ, тогава те могат да бъдат декриптирани само със съответния секретен ключ и обратно - ако данните са кодирани с частен ключ, тогава могат да бъдат декриптирани само със съответния публичен ключ. Невъзможно е да се използва публичен ключ от една двойка и секретен ключ от друга. Забележка: Асиметричното криптиране е частен случай на системите използващи множество от ключове (системи с неопределен брой ключове). Тези системи са обект на допълнителни разглеждания и са част от програмата на специализираните курсове. - Електронен подпис – използва се за установяване автентичността на документа, неговия произход и авторство. Елиминира възможността от несанкционирани изменения на информацията в електронните документи. - Битова схема (ангажираща схема, commitment scheme) – метод, който позволява на потребителят да потвърди достоверността на конкретна стойност. Стойността (която може да бъде число или значението на конкретен бит), би следвало да бъде секретна и да се оповестява само и единствено в случай на необходимост. В случаите на обмен на информация, тази стойност не може да бъде изменяна след като съобщението бъде изпратено. В някои източници този примитив е описан като „правило на затворения плик”. Този примитив е обвързан с т.н. квантово разпределение на секретните ключове. Забележка: Модифициран вариант на ангажираща схема се използва при нестандартните методи за криптиране, които са тема на отделно разглеждане. - Генератор на псевдослучайни числа (pseudorandom number generator, PRNG) – алгоритъм, генериращ псевдослучайни числа с определени свойства като независимост, равномерно разпределение и др.. 7. ОБЕДИНЯВАНЕ НА КРИПТОГРАФСКИ ПРИМИТИВИ Криптографичните примитиви са с ограничена функционалност, която не е в състояние да гарантира висока степен на надеждност. Използването само и единствено на шифровъчен алгоритъм не е достатъчно за съхраняване конфиденциалността на данните. Добрата практика изисква да се извършва обединение на няколко криптографски примитива в една обща система. Пример: Използването на комбинация между кодиращи функции (например DES) и хеширане (например SHA-1), позволяват на стандартната система за шифроване не само да шифрова информацията, но също така да я предпази от злоумишлени манипулации. Основните проблеми при криптографските системи са в резултат на неправилното използване на криптографски примитиви. Основните цели на криптозащитата са обвързани с оптимизирането на криптографската архитектура, както и с процесите на автоматизиране на провежданите анализи. ( край на първи раздел ) Забележка: Истински сериозните теми предстоят, Все пак е необходимо да говорим на един език и като начало е добре да усвоим предложената терминология. както вече споменах без математика няма да можем да минем, но ще се постарая да включа примери, които да позволят материята да бъде разбрана и усвоена, дори от тези, които мразят математиката. Оценяване и проверка на знанията След като сте усвоили достатъчно добре информацията в уводната част на курса може да пристъпите към самоподготовка и усъвършенстване на наученото. За целта може да използвате специализирани тестове (които се предоставят при поискване), или да участвате в дискусия, свързана с конкретната тематика. Решаване на тестово задание ви носи 30 т. Активно участие в дискусията (и аргунментирани и правилно оформени постове) добавя нови 30 т. За да получите още 40 т. трябва в рамките на седем календарни дни да изпълните писмено задани. Максималният брой точки, който може да получите е 100 т. Тези, коитъо постигнат резултат над 70 т. ще получат всички спомагателни материали за втората част от курса. Без тези приложения и ръководства няма да успеете да преминете следващите раздели.
  13. 5. ПРОТОКОЛ НА КОНФЕДЕНЦИАЛНИТЕ ИЗЧИСЛЕНИЯ (secure multi-party computation) Това е протокол на обмен на секретна информация, който се използва в случаите, когато е необходимо участниците да решават конкретни задачи, изискващи всеки един от тях да въведе конфиденциална информация, като при това другите участници не би следвало да получат пълен достъп до нея. ОПРЕДЕЛЕНИЕ Протокол на конфиденциални изчисления ще наричаме криптографски протокол, посредством който участниците в обмена на информация са в състояние да извършват определени действия, които са зависими от съхраняване на тайната на входните данни за всеки един от участниците в процеса. Основните изисквания при този протокол са: • Конфиденциалност – Никой от участниците не бива да получава повече информация от тази, която е предвидена за него. • Коректност – Всеки един от участниците в процеса трябва да има достъп до гарантирано достоверни резултати. • Гарантиран достъп до информация – Нито един от участниците не би следвало да може да блокира достъпа до резултати за другите участници в процеса. Съществуват два различни подхода на реализация на този протокол. При първият се използва разделяне на секрета. Протоколът използва аритметичен контур (arithmetic circuit). Такъв вид протокол е BGW (Ben-Or, Goldwasser и Wigderson). Този подход се прилага в случаите когато участниците са повече от двама. При него се изисква всеки един от участниците да е гарантирано честен. Този метод е подходящ, когато резултатите са следствие от математичски операции (събиране, умножение и др.). Не е подходящ за извършване на сравнения. При вторият подход се използва логически контур. Известен е още като метод на прекъснатата верига (garbled circuit). Такъв протокол е GMW (Goldreich, Micali и Wigderson). Методът е изключително подходящ в случаите когато се извършват бинарни операции, както и логически такива. Друго основно предимство е възможността този метод да бъде реализиран посредством използване на програмни езици от високо ниво. Протоколът на конфиденциални изчисления се използва при електронно гласуване, провеждане на електронни търгове (електронни аукциони), специфични статистически операции, при които изходните данни трябва да останат секретни и пр.. Хибридни протоколи за конфеденциалност (Hybrid Confederation Protocols - HCP) Съществуват и т.н. "хибридни кондфеденциални протоколи". Типичен пример за такъв вид протокол е използвания в FPS. При FPS протокола на конфиденциални изчисления се използва при работа с бази от данни (СУБД). Благодарение на него се гарантира, че заявката, подадена от оператора към базата от данни ще запази своя конфиденциален характер, без това по някакъв начин да повлияе на получените резултати. Също така FPS използва този протокол за разпределяне на сертификати между отделните потребители на системата, когато се използват стандартни методи за оторизиране. 6. КРИПТОГРАФСКИ ПРИМИТИВИ ОПРЕДЕЛЕНИЕ Под криптографски примитиви ще разбираме набор от алгоритми, които се използват при изграждането на криптографските протоколи за защита на информацията. В някои източници е възможно да се срещне определение, според което криптографските примитиви са функции и процедури, които определят работните параметри на криптосистемата. Криптографските примитиви са основните градивни елементи на всяка една криптосистема. Те са проектирани за ограничен кръг от задачи, за които се изисква висока степен на надеждност. Пример: Ако за дадена криптографска функция се твърди, че тя може да бъде компрометирана, посредством N на брой итерации, а реалният брой итерации, позволяващи несанкциониран достъп е N-1, се приема, че системата е ненадеждна от криптографска гледна точка. Ако броят на итерациите, използвани за дискредитиране на функцията е N+1, тя ще се счита за достатъчно надеждна. Изборът на надеждни примитиви, гарантира криптоустойчивостта на използваните протоколи. 6.1. УСЛОВИЕ ЗА НАДЕЖДНОСТ НА КРИПТОГРАФСКИТЕ СИСТЕМИ ОПРЕДЕЛЕНИЕ Една криптосистема ще се счита за достатъчно надеждна тогава и само тогава когато за всеки един от използваните за формиране на системата примитиви може да се докаже, че е достатъчно надежден. Ако само един от криптографските примитиви бъде компрометиран, всеки един от останалите , изграждащи протокола, се считат за компрометиран. 6.1.1. Свойства на криптографските примитиви Криптографските примитиви трябва да притежават следните свойства: - Ниво на сигурност – Под ниво на сигурност ще разбираме броя на необходимите операции (като при това се използват най-добрите методи, известни в момента методи и средства) за постигане на планираната цел. Обикновено нивото на сигурност се определя от горната граница на обема на работата, необходима за дискредитиране на криптографския модул. Прието е това да се нарича работещ фактор. - Функционалност - Примитивите трябва да позволяват комбиниране за постигане на различни цели. Кои примитиви ще се считат като най-ефективни за постигане на конкретна цел, ще зависи основно от техните свойства. - Метод на работа – Всеки един примитив би следвало да се използва по различен начин в зависимост от възникналата необходимост. - Ефективност - Ефективността на примитива в определен режим на работа. Например алгоритъмът за криптиране може да бъде оценен от количеството битовете, обработвани за единица време. - Експлотационна ефективност (простота) – Това е свойство, което е в пряка зависимост от процесите, свързани с практическа реализация на криптоалгоритъма. Прието е това да бъдат процесите на внедряване на примитивите в софтуерни или апаратни решения. Относителната тежест на различните критерии зависи от приложението и наличните ресурси. Например, в среда, в която изчислителната мощност е ограничена, може да се наложи отказ от високи нива на сигурност, за сметка на подобряване работата на системата като цяло.
  14. В тази тема ще се публикуват откъси от стандартният курс на Gate-92 DG "Въведение в приложната криптография" (Introduction to applied cryptography - проект IPC-3241). Това, което е важно да знаете е, че в редица случаи публикуваните материали ще бъдат в сериозно противоречие с масово разпространявани в internet материали по темата. Причината за това е, че в курса стриктно се съблюдават изискванията на международни и регионални стандарти. Ако някой прояви интерес, ще му бъдат предоставени допълнителни материали и ще получи официален сертификат. Важно е никога да не забравяте, че курсът е за "приложна", а не "теоретична" криптография и че това е само началото. Науката за криптиране на информация е много повече от шифроването на цифрови данни, но се надявам сами да се убедите в това, след като прочетете написаното. Има и още нещо, което е добре да се знае. Всички текстове са регистрирани в Electronic Copyright Office (eCO -United States Copyright Office) към Library of Congress. Тези текстове не са моя собственост. Нека бъдем коректни към колегите, които ни ги предоставиха, за да можем и занапред да получаваме много друга полезна информация от тях. Сега повечето от нас са по домовете си и може би е време да научим заедно нещо, което може да ни бъде от полза. Трябва да ценим времето си и да го използваме пълноценно. И така да започнем ... ВЪВЕДЕНИЕ В ПРИЛОЖНАТА КРИПТОГРАФИЯ част - I I. БАЗОВИ ТЕРМИНИ, ИЗПОЛЗВАНИ В СТАНДАРТНИТЕ МЕТОДИ НА ЗАЩИТА НА ИНФОРМАЦИЯТА 1. КОНФИДЕНЦИАЛНОСТ (от лат. Confidentia-доверие) ОПРЕДЕЛЕНИЕ Необходимост от предотвратяване на достъпа на неоторизирани (неупълномощени) за това лица до определена информация. Под конфеденциална информация би следвало да разбираме информация, достъпът до която е ограничен. Такъв вид информация още се нарича секретна, чувствителна или тайна. В страните от Европейския съюз въпросите, свързани с конфиденциалната информация са урегулирани с редица регламенти и директиви като директива ЕС 95/46/ЕС, 2002/58/ЕС и ETS 108, ETS 181, ETS 185, ETS 189 и др. 2. ИНФОРМАЦИОННА БЕЗОПАСНОСТ (Information Security) ОПРЕДЕЛЕНИЕ Набор от решения за предотвратяване на несанкциониран достъп, незаконно използване, злоумишлено редактиране или унищожаване на информационни масиви. Терминът не е обвързан с вида на информацията (цифрова, аналогова или друг вид). Основната задача на информационната безопасност е да се гарантира конфиденциалността, без това по някакъв начин това да се отразява на нормалното функциониране на структурата и спомагателните процеси. Информационната безопасност е елемент от процесите, свързани с управлението на риска. Тя позволява идентификация на основните материални и нематериални средства, които съдържат някаква форма на уязвимост. Всяка доказана форма на уязвимост е в състояние да дискредитира системите, гарантиращи конфиденциалния характер на информацията. Ефективността на мерките е в пряка зависимост от правилното планиране, превенцията и определяне приоритетите, съобразно степента на въздействие на отделните елементи, от които е изградена системата за сигурност. 3. КРИПТОГРАФСКИ ПРОТОКОЛ (Cryptographic Protocol) ОПРЕДЕЛЕНИЕ Абстрактен или конкретен протокол, който обединява набор от криптографски алгоритми. В основата на протокола са набор от правила, регламентиращи използваните криптографични преобразования и алгоритми в информационните процеси. 4. КОМУНИКАЦИОНЕН ПРОТОКОЛ ОПРЕДЕЛЕНИЕ Последователност от действия, осъществявани в процеса на информационен обмен. Комуникационният протокол обезпечава установяване сеанс на връзка (обмен), избор на маршрут, възстановяване на данните и отстраняване на грешки и др.. До каква степен един комуникационен протокол се счита за надежден, зависи от сервизните функции, гарантиращи безопасността. Те определят параметри като достъпност, конфиденциалност, цялост на информационните масиви и пр.. Сервизните функции не бива да се бъркат с математическото понятие „функция”. Всеки един протокол, обезпечаващ поддръжката на поне една сервизна функция, обслужваща системите за безопасност се счита за защитен протокол (security protocol) Механизмите за защита допълват или са елемент от комуникационните протоколи. . . . следва продължение ... Забележка: Искам да обърна специално внимание на дефиницията на "комуникационен протокол". В бъдеще многократно ще се връщаме към темата, като често това ще бъде обвързано с масово допускани грешки. Прието е примерите за криптография да бъдат обвързани с желанието на Алис и Боб да комуникират, но това е частен случай, с всички произтичащи от това последици. В науката подходът е "от общо към частно", а не обратно. В конкретния курс ще се придържаме към доказани, фундаментални принципи. Когато бъдат добре усвоени ще говорим за по-сериозни неща, но там ще е нужно да обясним базови понятия от висшата математика, така че да бъдат не просто разбрани, а и да можете да ги ползвате максимално ефективно в ежедневната си практика.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.