<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Maciej[cc] &#187; kryptografia</title><atom:link href="https://nabozny.io/tag/kryptografia/index.xml" rel="self" type="application/rss+xml"/><link>https://nabozny.io/tag/kryptografia/</link><description>Blog o programowaniu i nie tylko</description><lastBuildDate>Sun, 24 Nov 2019 16:47:03 +0000</lastBuildDate><language>pl-PL</language><generator>Hugo 0.167.0</generator><item><title>Dinemic promo video</title><link>https://nabozny.io/dinemic-promo-video/</link><dc:creator>maciej</dc:creator><pubDate>Sun, 24 Nov 2019 16:47:03 +0000</pubDate><category>Inne</category><category>kryptografia</category><category>dinemic</category><category>blender</category><guid isPermaLink="true">https://nabozny.io/dinemic-promo-video/</guid><description>W ostatnim czasie udało mi się z pomocą kilku osób stworzyć nowe video dla projektu Dinemic. Miłego oglądania :)</description><content:encoded>&lt;p&gt;W ostatnim czasie udało mi się z pomocą kilku osób stworzyć nowe video dla projektu Dinemic. Miłego oglądania :)&lt;/p&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/V6ztp4vu1d0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;&#10;&#10;&lt;p&gt;Video w całości wykonane w Blenderze, czas renderowania, o zgrozo, 3 i pół dnia. Render cycles, z włączonym AO, składanie ffmpeg. Strona projektu: &lt;a href="https://dinemic.io"&gt;dinemic.io&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Jak trzymać hasła w pamięci i dlaczego cstringi są czasem lepsze od std::stringów?</title><link>https://nabozny.io/jak-trzymac-hasla-w-pamieci-i-dlaczego-cstringi-sa-czasem-lepsze-od-stdstringow/</link><dc:creator>maciej</dc:creator><pubDate>Sat, 16 Feb 2019 08:32:37 +0000</pubDate><category>Programowanie</category><category>Cloud</category><category>Linux</category><category>kryptografia</category><category>programowanie</category><category>linux</category><guid isPermaLink="true">https://nabozny.io/jak-trzymac-hasla-w-pamieci-i-dlaczego-cstringi-sa-czasem-lepsze-od-stdstringow/</guid><description>“Poznaj sekret cstringów. Std::stringi ich za to nienawidzą”! A na serio, nie zgapiając od pomponików, będzie trochę na temat trzymania wrażliwych danych w pamięci RAM i o zapobieganiu ich zapisowi na dysk.</description><content:encoded>&lt;p&gt;&amp;ldquo;Poznaj sekret cstringów. Std::stringi ich za to nienawidzą&amp;rdquo;! A na serio, nie zgapiając od pomponików, będzie trochę na temat trzymania wrażliwych danych w pamięci RAM i o zapobieganiu ich zapisowi na dysk.&lt;/p&gt;&#10;&lt;p&gt;Na początek krótkie ćwiczenie: napisałeś program do przechowywania haseł. Taki keepass w wersji DIY. Po uruchomieniu wczytuje zaszyfrowany plik do pamięci, pyta Cię o hasło, odszyfrowuje i pokazuje wybrane hasło. Działa dopóki go nie zamkniesz, na wszelki wypadek, jakbyś potrzebował jeszcze innego hasła. Niby bezpieczne, bo zaszyfrowane, na hasło&amp;hellip; ale nie do końca.&lt;/p&gt;&#10;&lt;h3 id="co-może-pójść-nie-tak"&gt;Co może pójść nie tak?&lt;/h3&gt;&#10;&lt;p&gt;Trzymasz odszyfrowany pęk kluczy w pamięci – to pierwszy problem. Dowolne nadpisanie/odczytanie takiej pamięci, np. przez /dev/mem albo /proc/X/mem może skompromitować wszystkie hasła z Twojego pęku – dowolna osoba z uprawnieniami root&amp;rsquo;a będzie mogła wczytać treść z Twojej pamięci. To może odszyfrowywać tylko gdy tego potrzebujemy? Ok, wtedy trzymamy w pamięci jedynie nasze główne hasło i zaszyfrowane przez prawie cały czas dane.&lt;/p&gt;&#10;&lt;p&gt;Osoba atakująca będzie mogła wtedy dość łatwo poznać hasło, którego możesz też przecież używać gdzieś indziej (tak, są tacy ludzie i jest ich dość dużo :) ). Popatrzmy na inny przykład: Linux Kernel posiada wbudowany system szyfrowania dysków – LUKS. Do odszyfrowania jednego dysku można przypisać kilka różnych haseł dla różnych osób. Dzięki temu można uniknąć przekazywania ich i zapisywania na karteczkach. Każdy może użyć wtedy swojego ulubionego hasła :) Jeśli natomiast je zgubi, można zmienić tylko to jedno hasło do dysku, bez zmiany innych haseł. Co więcej zmiana dowolnego hasła nie wymusza re-szyfrowania całego dysku. Jak to działa? Nie ma za tym jakiejś specjalnej magii i matematyki. Każdy z użytkowników, którzy mają swoje hasła tak na prawdę deszyfruje główny klucz do dysku. Dopiero za pomocą tego klucza jest przeprowadzane pełne (de)szyfrowanie.&lt;/p&gt;&#10;&lt;p&gt;Podobny mechanizm możesz też zastosować w Twoim pęku kluczy lub podobnej aplikacji. Za pomocą hasła użytkownik może odszyfrować tak na prawdę klucz symetryczny, który posłuży do odczytania pozostałej części danych. Przechowywanie go w pamięci, jeśli to konieczne, jest wtedy nieco bardziej bezpiecznym rozwiązaniem niż ciągłe przechowywanie hasła, lub co gorsze pełnego pęku kluczy.&lt;/p&gt;&#10;&lt;h3 id="gdzie-zapisać-tymczasowe-hasło"&gt;Gdzie zapisać tymczasowe hasło?&lt;/h3&gt;&#10;&lt;p&gt;Mimo wszystko Twoje hasło lub klucz deszyfrujący musi być tak czy tak chociaż na chwilę wczytane do pamięci. Jak zabezpieczyć się przed jego wyciekiem? Oprócz możliwości odczytania hasła bezpośrednio z pamięci jest jeszcze jedna możliwość. Atakujący może zaalokować tak dużo pamięci w systemie, że w końcu Twój DIY Keepass zostanie przeniesiony do swapu. A stąd już prosta droga do wyciągnięcia i przeanalizowania danych. Jeśli nie jako dump pamięci z poziomu roota, to śrubokrętem, przenosząc dysk do innego komputera lub bootując komputer z live cd.&lt;/p&gt;&#10;&lt;p&gt;Jak się przed tym obronić? Linux posiada trzy funkcje pozwalające Twojej aplikacji określić jak ma się zachowywać jej wirtualna pamięć. Pierwsza z nich to &lt;a href="https://linux.die.net/man/2/mprotect"&gt;&lt;em&gt;mprotect&lt;/em&gt;&lt;/a&gt;. Podając adres pamięci (np. blok zwrócony przez &lt;em&gt;malloc&lt;/em&gt;) możesz sprawić, że dany obszar będzie dostępny tylko do odczytu, do zapisu lub w cale. Flaga &lt;em&gt;PROT_WRITE&lt;/em&gt; jest zwykle stosowana do zabezpieczenia obszaru pamięci, w którym znajduje się Twój plik wykonywalny, aby przypadkowe (lub złośliwe) nadpisanie kodu instrukcji Twojej aplikacji nie było możliwe. &lt;em&gt;PROT_EXEC&lt;/em&gt; jest natomiast stosowane do zabezpieczenia pamięci przed wykonywaniem jej kodu, np. w obszarach pamięci przechwujących zmienne. Zapobiega do przypadkowemu uruchomieniu takiego kodu. Wbrew pozorom bardzo użyteczną flagą może być &lt;em&gt;PROT_NONE&lt;/em&gt;. Takiego obszaru nie da się ani odczytać, ani zmodyfikować ani wykonać. Jedną stronę takiej pamięci możemy ustawić np. za obszarem, do którego będą zapisywane dane od użytkownika, o nieznanym rozmiarze. Jeśli nasze programowe zabezpieczenia zawiodą i na przykład zaczniemy zapisywać do takiej tablicy bez opamiętania (bez if&amp;rsquo;a :) to finalnie program spróbuje zapisać coś na stronie pamięci oznaczonym &lt;em&gt;PROT_NONE&lt;/em&gt;. W takiej sytuacji zadziała już sprzętowe zabezpieczenie i nasza aplikacja otrzyma stosowny, zwykle bolesny sygnał od systemu operacyjnego.&lt;/p&gt;&#10;&lt;p&gt;Drugą funkcją służącą do modyfikowania zachowania pamięci jest &lt;a href="http://man7.org/linux/man-pages/man2/madvise.2.html"&gt;&lt;em&gt;madvise&lt;/em&gt;&lt;/a&gt;. Podobnie jak &lt;em&gt;mprotect&lt;/em&gt; przyjmuje ona adres i rozmiar obszaru pamięci, który chcemy zmodyfikować. Za jej pomocą możemy powiedzieć systemowi (doradzić) jak będziemy korzystać z tego obszaru. Czy na przykład będą to losowe odczyty i cache&amp;rsquo;owanie na wyrost nie ma sensu, czy też podczas forka procesu ten obszar pamięci ma pozostać nieskopiowany. Flag jest sporo, warto przeglądnąć je w przyjaznym manualu.&lt;/p&gt;&#10;&lt;p&gt;Ostatnia funkcja, warta wspomnienia to &lt;em&gt;mlock&lt;/em&gt;. Ponownie, przyjmuje jako pierwsze parametry adres i rozmiar obszaru pamięci. Zapobiega ona przenoszeniu stron pamięci na swap. Oznaczając w ten sposób obszar gdzie trzymamy klucz deszyfrujący oraz sam keychain, możemy zabezpieczyć się przed wspomnianym wcześniej wymuszeniem zrzutu pamięci na swap.&lt;/p&gt;&#10;&lt;p&gt;Korzystając z wszystkich trzech powyższych funkcji możemy wymusić na systemie operacyjnym nieco lepsze potraktowanie naszych danych przesiadujących w pamięci. Za pomocą &lt;em&gt;mprotect&lt;/em&gt; możemy przez większość czasu zapobiegać dostępowi do pamięci, ustawiając jej flagę &lt;em&gt;PROT_NONE&lt;/em&gt;, i &amp;ldquo;odbezpieczając&amp;rdquo; tylko gdy użytkownik potrzebuje hasła. Za pomocą &lt;em&gt;madvise&lt;/em&gt; mona zapobiec skopiowaniu tej pamięci przez fork (i prawdopodobnie zabezpieczyć się też na kilka innych okoliczności), a z &lt;em&gt;mlock&lt;/em&gt; zapobiegniemy wyrzuceniu na swap.&lt;/p&gt;&#10;&lt;h3 id="cstring-vs-stdstring"&gt;Cstring vs. std::string&lt;/h3&gt;&#10;&lt;p&gt;Przy okazji wychodzi czemu czasami zarządzanie pamięcią przez &lt;em&gt;malloc&lt;/em&gt; i standardowe stringi z C są bardziej użyteczne. Korzystając z &lt;em&gt;std::string&lt;/em&gt; nie mamy tak dokładnej kontroli nad tym, gdzie będą trzymane dane ze stringa, jak również nie mamy gwarancji że po dopisaniu kolejnych znaków nie zostanie on w całości przeniesiony w inne miejsce. Trudniejsze staje się też zabezpieczenie strony tuż za stringiem. Nie jest to jednak niemożliwe, jednak wymaga dodatkowej pracy i dogłębnej wiedzy jak jest alokowana w tym przypadku pamięć. Dodatkowo, gdy std::string zwalnia pamięć, musimy też ręcznie posprzątać po nim, aby inny obiekt nie dostał obszaru z &lt;em&gt;PROT_NONE&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p&gt;W przypadku c stringów, wszystkie operacje przenoszenia, zabezpieczania i odbezpieczania musimy zrobić tak czy tak ręcznie, jednak z punktu widzenia czytelności kodu i jego obsługi jest to znacznie czytelniejsze.&lt;/p&gt;&#10;&lt;h3 id="swap-też-jest-szyfrowany"&gt;Swap też jest szyfrowany&lt;/h3&gt;&#10;&lt;p&gt;Tak, od jakiegoś czasu dystrybucje wspierają to domyślnie. Strony pamięci zrzucane do swapu są w locie szyfrowane, także odczytanie ich po wyłaczeniu komputera nieco się komplikuje. Przykładowy wpis z Arch wiki:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;swap /dev/sdX# /dev/urandom swap,cipher=aes-xts-plain64,size=256&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Przy każdym starcie system generuje losowy klucz do zaszyfrowania swapu z /dev/urandom. Nawet jeśli coś się na swapie pojawi, to będą to tylko losowe znaki dla osoby, która nie zna klucza. Problem pojawia się jednak przy wsparciu dla disk suspend – uśpienia komputera i zrzucenia stanu pamięci na dysk. W tym przypadku sprawy się nieco komplikują, ale to historia na inny wpis.&lt;/p&gt;&#10;&lt;h3 id="wirtualne-maszyny"&gt;Wirtualne maszyny&lt;/h3&gt;&#10;&lt;p&gt;O ile wszystkie powyższe sposoby mają się całkiem dobrze na &amp;ldquo;gołym&amp;rdquo; PC, to już korzystając z wirtualizacji nie mamy gwarancji, że ktoś nie zrobi zrzutu pamięci oraz dysku w locie i nie będzie próbował analizować tego offline. W takim wypadku jedynym rozwiązaniem minimalizującym ryzyko przechwycenia cennych danych jest tylko chwilowe odszyfrowywanie ich. Nie gwarantuje to jednak pełnego bezpieczeństwa. Na własnych systemach można zapobiegać temu odpowiednimi opcjami dla wirtualnych maszyn, dzięki którym gospodarz nie będzie przenosił ich stron na swap. Służy do tego m.in. opcja &lt;a href="https://libvirt.org/formatdomain.html#elementsMemoryBacking"&gt;&lt;em&gt;locked&lt;/em&gt;&lt;/a&gt; w libvircie. Jednak w publicznych chmurach nie mamy takiej gwarancji.&lt;/p&gt;&#10;&lt;h3 id="bezpieczeństwo-różnych-algorytmów"&gt;Bezpieczeństwo różnych algorytmów&lt;/h3&gt;&#10;&lt;p&gt;Na koniec warto wspomnieć o bezpieczeństwie samych algorytmów szyfrujących. Co, jeśli któryś okaże się podatny na ataki? Często aplikacje oferujące szyfrowanie pozwalają na złożenie kilku algorytmów na raz. O ile Twoje hasło pozostaje prawdopodobnie najsłabszym punktem, to szansa na skompromitowanie dwóch algorytmów szyfrujących na raz znacznie spada. Pomyśl, że lata temu używałeś MD5 do potwierdzania integralności plików. Algorytm się &amp;ldquo;zepsuł&amp;rdquo;. Wykonanie SHA1(MD5(&amp;hellip;)) nieco ratuje sprawę. W ten sposób zabezpieczają się np. adresy portfeli z Ethereum. Skompromitowanie jednego algorytmu (co powodowałoby że łatwo wygenerować inny portfel z tym samym adresem) znacznie maleje.&lt;/p&gt;</content:encoded></item><item><title>Libsodium – kryptografia w łatwiejszym wydaniu</title><link>https://nabozny.io/libsodium-kryptografia-w-latwiejszym-wydaniu/</link><dc:creator>maciej</dc:creator><pubDate>Fri, 21 Jul 2017 21:45:40 +0000</pubDate><category>Programowanie</category><category>kryptografia</category><category>programowanie</category><category>C++</category><guid isPermaLink="true">https://nabozny.io/libsodium-kryptografia-w-latwiejszym-wydaniu/</guid><description>Już kilka razy potrzebowałem użyć kryptografii do jakiegoś zadania. Zwykle przychodził z “pomocą” potworek o nazwie openssl, za pomocą którego można było wyczarować cuda. Problemem była jedynie składnia, którą trudno zapamiętać, bo “potworek” jest szyty na miarę profesjonalnych zastosowań.</description><content:encoded>&lt;p&gt;Już kilka razy potrzebowałem użyć kryptografii do jakiegoś zadania. Zwykle przychodził z &amp;ldquo;pomocą&amp;rdquo; potworek o nazwie &lt;em&gt;openssl&lt;/em&gt;, za pomocą którego można było wyczarować cuda. Problemem była jedynie składnia, którą trudno zapamiętać, bo &amp;ldquo;potworek&amp;rdquo; jest szyty na miarę profesjonalnych zastosowań.&lt;/p&gt;&#10;&lt;p&gt;API &amp;ldquo;potworka&amp;rdquo; jest jeszcze bardziej pokręcone i wymaga ogromnej wiedzy, już na sam początek, co dla niewprawionych w bojach z kryptografią może być i tak bardzo dużym wyzwaniem.&lt;/p&gt;&#10;&lt;p&gt;Niedawno, szukając jakiejś alternatywy dla wołania zewnętrznego polecenia openssl albo gpg, dla projektu &lt;a href="https://github.com/cloudover/libdinemic/"&gt;libdinemic&lt;/a&gt; udało mi się znaleźć bibliotekę Sodium, która jest następcą innego, ponoć podobnego narzędzia NaCl. Biblioteka ta pozwala w bardzo przyjemny sposób ogarnąć podstawowe zadania związane z kryptografią:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Podpisy cyfrowe – generujące kawałek danych potwierdzający, że właściciel prywatnego klucza coś napisał&lt;/li&gt;&#10;&lt;li&gt;Szyfrowanie symetryczne – pozwalające zamienić ciąg ważnych dla nas danych w (prawie) bezużyteczne śmieci, możliwe do odszyfrowania jedynie po podaniu hasła&lt;/li&gt;&#10;&lt;li&gt;Szyfrowanie asymetryczne – pozwalające zaszyfrowanie komuś danych posiadając jedynie jego publiczny, znany wszystkim klucz. Dzięki temu tylko ta osoba ta może odszyfrować, korzystając z prywatnej części klucza&lt;/li&gt;&#10;&lt;li&gt;Funkcje skrótu SHA2&lt;/li&gt;&#10;&lt;li&gt;&amp;hellip; i kilka innych fajnych narzędzi związanych z bezpieczeństwem&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="jak-się-za-to-zabrać"&gt;Jak się za to zabrać?&lt;/h3&gt;&#10;&lt;p&gt;Będziesz potrzebował samą bibliotekę, jej pliki nagłówkowe, kompilator i edytor tekstu:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install libsodium-dev gcc gedit&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aby skompilować coś, co zachwile stworzysz, dodaj opcję &lt;em&gt;-lsodium&lt;/em&gt; do kompilatora:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcc -o program -lsodium program.c&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;lub skorzystaj z gotowego narzędzia typu &lt;em&gt;make&lt;/em&gt;, &lt;em&gt;qmake&lt;/em&gt; albo &lt;em&gt;cmake&lt;/em&gt;.&lt;/p&gt;&#10;&lt;h3 id="klucz-prywatny-i-publiczny--po-co-to"&gt;Klucz prywatny i publiczny – po co to&lt;/h3&gt;&#10;&lt;p&gt;Zanim przejdziemy do kolejnych kroków – kilka zdań o kryptografii asymetrycznej. Jak źle by to nie było omówione na studiach, warto wiedzieć co ona daje i wierzyć, że jeszcze nikt z NSA nie złamał jej zabezpieczeń (albo i nie wierzyć). W dużym uproszczeniu, kryptografia asymetryczna bazuje na parach kluczy (liczb), z których jedna, prywatna, to zwykle duża losowa liczba. W niektórych algorytmach musi to być liczba pierwsza. Druga liczba, publiczna jest obliczana na podstawie tej pierwszej, prywatnej.&lt;/p&gt;&#10;&lt;p&gt;Generowanie drugiej liczny jest wykonywane w taki sposób, aby operacja odwrotna była bardzo żmudna i długotrwała. Dobrym porównaniem jest mieszanie farbek. Jeśli znasz proporcje (Twój klucz prywatny), to możesz szybko wymieszać podstawowe kolory i otrzymać identyfikujący Cię kolor. Każda wiadomość pomaziana Twoim kolorem będzie automatycznie oznaczona jako nadana przez Ciebie, bo tylko Ty potrafisz zrobić taki kolor. Jeśli natomiast ktoś chciałby podrobić Twój kolor, to musiałby próbować różnych zestawień barw, co trwało by znacznie dłużej. Podobnie miało to miejsce z tajną recepturą KFC. Wszyscy próbowali ją podrabiać, ale do czasu jej wycieku oryginalny smak, bazujący na proporcjach kilkunastu przypraw pozostawał tylko w KFC.&lt;/p&gt;&#10;&lt;p&gt;O ile kolory czy proporcje przypraw można by próbować dość łatwo odtworzyć, bo nie ma aż tylu możliwości, to obliczenie prywatnego klucza kryptograficznego (proporcji przypraw) na podstawie klucza publicznego (smaku) może trwać zwykle latami na pojedynczym komputerze. Dla tego jest to uznawane za bezpieczny środek komunikacji, a dodatkowo daje możliwość udostępnienia wszystkim czegoś (smaku, koloru, publicznego klucza), który może zweryfikować czy to my lub umożliwić zaszyfrowanie nam wiadomości, którą odczytamy tylko my.&lt;/p&gt;&#10;&lt;h3 id="podpisy-cyfrowe"&gt;Podpisy cyfrowe&lt;/h3&gt;&#10;&lt;p&gt;Pierwszym zadaniem z &lt;em&gt;libsodium&lt;/em&gt; było dla mnie zakodowanie modułu umożliwiającego generowanie podpisów cyfrowych w &lt;em&gt;libdinemic&lt;/em&gt;. Miało to uwierzytelnić każdą zmianę wykonywaną w rozproszonej bazie dla wielu hostów, bez korzystania z blokad i tym podobnych mechanizmów. W zamian miały być wykorzystane właśnie podpisy cyfrowe – tylko osoba posiadająca klucz prywatny przypisany do obiektu w bazie może go zaktualizować.&lt;/p&gt;&#10;&lt;p&gt;Jak wygenerować taki podpis za pomocą &lt;em&gt;libsodium&lt;/em&gt;? Potrzebujemy wiadomość (update stanu bazy) oraz parę kluczy, prywatny i publiczny. Klucze można wygenerować jedną funkcją:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sodium.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;sign_secret_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_sign_SECRETKEYBYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;sign_public_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_sign_PUBLICKEYBYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;crypto_sign_keypair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sign_public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sign_secret_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;crypto_sign_keypair&lt;/em&gt; zapisze do podanych zmiennych klucz prywatny (losowy ciąg danych) i odpowiadający mu klucz publiczny. Libsodium używa do tego algorytmów opartych o krzywe eliptyczne, przez co klucze są znacznie krótsze od tych znanych z RSA. Mając dwa klucze możemy wygenerować wiadomość i podpisać ją cyfrowo naszym prywatnym kluczem:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_sign_BYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Ala ma kota a kot ma Ale&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;crypto_sign_detached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sign_secret_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podpis cyfrowy będzie zapisany do zmiennej sig, która ma stałą, określoną przez crypto_sign_BYTES długość.&lt;/p&gt;&#10;&lt;p&gt;W ten sposób możemy rozpowszechnić nasz publiczny klucz, za pomocą którego inne osoby lub programy będą mogły potwierdzić autentyczność naszej wiadomości. Aby zweryfikować podpisany ciąg znaków wystarczy sprawdzić:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_sign_BYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;//pobieramy podpis&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;//pobieramy wiadomość&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crypto_sign_verify_detached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sign_public_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// To jest fałszywy podpis!&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Podpis się zgadza&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="szyfrowanie-danych"&gt;Szyfrowanie danych&lt;/h3&gt;&#10;&lt;p&gt;Szyfrowanie danych z libsodium wygląda podobnie, aczkolwiek wymaga użycia innego zestawu funkcji i algorytmów. Po pierwsze musimy wygenerować inny zestaw kluczy za pomocą innej funkcji – &lt;em&gt;crpto_box_keypair&lt;/em&gt;:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;encryption_secret_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_box_SECRETKEYBYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;encryption_public_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;crypto_box_PUBLICKEYBYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;crypto_box_keypair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryption_public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encryption_secret_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Następnie możemy rozpowszechnić publiczny klucz. Szyfrowanie działa trochę inaczej – tutaj do wygenerowania danych nadawcy potrzebny jest publiczny klucz. Dzięki temu tylko odbiorca może odszyfrować swoją wiadomość. Odwrotnie było w przypadku podpisów – tylko nadawca mógł się podpisać pod wiadomością, a zweryfikować mógł ktokolwiek, używając jego klucza publicznego.&lt;/p&gt;&#10;&lt;p&gt;Do zaszyfrowania wiadomości będziemy potrzebowali dodatkowego obszaru pamięci, do którego libsodium zapisze zaszyfrowane dane:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Ala ma kota a kot nie ma Ali&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;encrypted_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;crypto_box_SEALBYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;crypto_box_seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encryption_public_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Wysylamy wiadomosc w swiat&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Odbiorca wiadomości może ją odszyfrować posiadając swój prywatny klucz:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Odebranie wiadomosci&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;decrypted_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;encrypted_message_length&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;crypto_box_seal_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decrypted_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encrypted_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encrypted_message_length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encryption_public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;encryption_secret_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// nie udalo sie odszyfrowac wiadomosci&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Mamy wiadomosc!&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do powyższych przykładów należy podejść czysto edukacyjnie i zwrócić uwagę zwłaszcza na funkcje &lt;em&gt;strlen&lt;/em&gt;, które w przypadku danych binarnych mogą zwrócić niepoprawne wartości.&lt;/p&gt;</content:encoded></item></channel></rss>