{
  "version": "https://jsonfeed.org/version/1",
  "title": "gruszka.dev",
  "home_page_url": "https://gruszka.dev",
  "feed_url": "https://gruszka.dev/archive-2025.json",
  "description": "Things I would like to share",
  "items": [
    {
      "id": "https://gruszka.dev/rsa.html",
      "url": "https://gruszka.dev/rsa.html",
      "title": "RSA – czyli jak działa szyfrowanie asymetryczne bez czarnej magii",
      "content_html": "<p>Parę tygodni temu ktoś mnie zapytał: <em>„Ej, a tak normalnie, po ludzku – jak działa RSA?”</em>.</p>\n<p>No i pomyślałem: <strong>OK, spróbuję to wytłumaczyć</strong>, bo temat jest ważny, a często tłumaczony strasznie akademicko.</p>\n<p>Wyobraźcie sobie, że chcecie wysłać komuś tajną wiadomość przez Internet. Wszyscy patrzą, wszyscy podsłuchują.</p>\n<p>Jak to zrobić, żeby <strong>tylko odbiorca</strong> mógł ją przeczytać? No właśnie tu wchodzi cały algorytm RSA, cały na biało ;)</p>\n<hr />\n<h2><a href=\"#o-co-w-ogóle-chodzi-z-rsa\" aria-hidden=\"true\" class=\"anchor\" id=\"o-co-w-ogóle-chodzi-z-rsa\"></a>O co w ogóle chodzi z RSA?</h2>\n<p>RSA<sup class=\"footnote-ref\"><a href=\"#fn-1\" id=\"fnref-1\" data-footnote-ref>1</a></sup> to <strong>algorytm kryptografii asymetrycznej</strong>. Brzmi groźnie, ale idea jest prosta:</p>\n<ul>\n<li>masz <strong>dwa klucze</strong>:\n<ul>\n<li><strong>publiczny</strong> – możesz go dać całemu światu</li>\n<li><strong>prywatny</strong> – tego pilnujesz jak oka w głowie</li>\n</ul>\n</li>\n<li>co zaszyfrujesz kluczem publicznym, <strong>da się odszyfrować tylko prywatnym</strong></li>\n</ul>\n<p>Można powiedzieć, że to taka kłódka, do której każdy ma klucz do zamykania, ale tylko ty masz klucz do otwierania ;)</p>\n<hr />\n<h2><a href=\"#skąd-się-biorą-te-klucze\" aria-hidden=\"true\" class=\"anchor\" id=\"skąd-się-biorą-te-klucze\"></a>Skąd się biorą te klucze?</h2>\n<p>No dobra, tu zaczyna się matematyka, ale spokojnie – bez paniki.</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-mermaid\">flowchart TD\n    Start([🚀 START&lt;br/&gt;Generowanie kluczy RSA])\n\n    Start --&gt; P1[Wybierz dwie duże liczby pierwsze&lt;br/&gt;p = 61, q = 53]\n\n    P1 --&gt; P2[Oblicz n = p × q&lt;br/&gt;n = 61 × 53 = 3233]\n\n    P2 --&gt; P3[Oblicz funkcję Eulera&lt;br/&gt;φ'n' = 'p-1' × 'q-1'&lt;br/&gt;φ'n' = 60 × 52 = 3120]\n\n    P3 --&gt; P4[Wybierz wykładnik publiczny e&lt;br/&gt;względnie pierwszy z φ'n'&lt;br/&gt;e = 17]\n\n    P4 --&gt; P5[Oblicz wykładnik prywatny d&lt;br/&gt;odwrotność modularna e mod φ'n'&lt;br/&gt;d = 2753]\n\n    P5 --&gt; Check{Sprawdzenie:&lt;br/&gt;'e × d' mod φ'n' = 1?}\n\n    Check --&gt;|✅ TAK&lt;br/&gt;17 × 2753 mod 3120 = 1| Success[✅ GOTOWE!&lt;br/&gt;&lt;br/&gt;🔓 Klucz publiczny: 'e, n' = '17, 3233'&lt;br/&gt;🔐 Klucz prywatny: 'd, n' = '2753, 3233']\n\n    Check --&gt;|❌ NIE| P4\n\n    Success --&gt; End([🎉 Klucze wygenerowane])\n\n    style Start fill:#e1f5ff,stroke:#0066cc,stroke-width:3px\n    style Success fill:#d4edda,stroke:#28a745,stroke-width:3px\n    style End fill:#d4edda,stroke:#28a745,stroke-width:3px\n    style Check fill:#fff3cd,stroke:#ffc107,stroke-width:2px\n    style P5 fill:#ffe6e6,stroke:#dc3545,stroke-width:2px\n</code></pre>\n<h3><a href=\"#krok-1-wybieramy-dwie-liczby-pierwsze\" aria-hidden=\"true\" class=\"anchor\" id=\"krok-1-wybieramy-dwie-liczby-pierwsze\"></a>Krok 1: wybieramy dwie liczby pierwsze</h3>\n<p><strong>Ale czekaj – co to w ogóle jest liczba pierwsza?</strong></p>\n<p>To liczba, która dzieli się <strong>tylko przez 1 i przez samą siebie</strong>.</p>\n<p>Przykłady:</p>\n<ul>\n<li><strong>2, 3, 5, 7, 11, 13, 17, 19, 23...</strong> – to liczby pierwsze ✓</li>\n<li><strong>4</strong> (dzieli się przez 2), <strong>6</strong> (dzieli się przez 2 i 3), <strong>8</strong> (dzieli się przez 2 i 4) – to NIE są liczby pierwsze ✗</li>\n</ul>\n<p>Liczby pierwsze to takie &quot;atomy matematyki&quot; – nie da się ich rozłożyć na mniejsze kawałki.</p>\n<div class=\"markdown-alert markdown-alert-note\">\n<p class=\"markdown-alert-title\">Dlaczego liczby pierwsze?</p>\n<p>Ta właściwość jest <strong>fundamentem bezpieczeństwa RSA</strong>! Liczby pierwsze są łatwe do pomnożenia, ale ich iloczyn jest praktycznie niemożliwy do rozłożenia z powrotem (dla dużych liczb).</p>\n</div>\n<p><strong>OK, do rzeczy:</strong></p>\n<p>Na start wybierasz <strong>dwie duże liczby pierwsze</strong>:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">p = 61\nq = 53\n</code></pre>\n<p>(W praktyce to są liczby mające setki cyfr, ale na bloga wystarczy coś mniejszego).</p>\n<h3><a href=\"#krok-2-mnożymy-je-przez-siebie\" aria-hidden=\"true\" class=\"anchor\" id=\"krok-2-mnożymy-je-przez-siebie\"></a>Krok 2: mnożymy je przez siebie</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">n = p * q = 3233\n</code></pre>\n<p>Ta liczba <code>n</code> będzie częścią <strong>klucza publicznego</strong>. I tak – każdy może ją znać.</p>\n<hr />\n<h2><a href=\"#magia-czyli-funkcja-eulera\" aria-hidden=\"true\" class=\"anchor\" id=\"magia-czyli-funkcja-eulera\"></a>Magia (czyli funkcja Eulera)</h2>\n<p>Teraz liczymy tzw. <strong>funkcję Eulera</strong>:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">φ(n) = (p - 1) * (q - 1)\nφ(n) = 60 * 52 = 3120\n</code></pre>\n<h3><a href=\"#co-to-w-ogóle-znaczy\" aria-hidden=\"true\" class=\"anchor\" id=\"co-to-w-ogóle-znaczy\"></a>Co to w ogóle znaczy?</h3>\n<p>φ(n) (czytaj: &quot;fi od en&quot;) mówi nam, <strong>ile liczb jest względnie pierwszych z n</strong>.</p>\n<p><strong>Ale czekaj – co to znaczy &quot;względnie pierwsze&quot;?</strong></p>\n<p>Dwie liczby są względnie pierwsze, gdy <strong>nie mają wspólnych dzielników</strong> (oprócz 1).\nCzyli ich największy wspólny dzielnik (NWD) = 1.</p>\n<p><strong>Przykłady:</strong></p>\n<ul>\n<li>8 i 9 → względnie pierwsze (NWD=1), ale żadna nie jest liczbą pierwszą!</li>\n<li>6 i 9 → NIE są względnie pierwsze (NWD=3)</li>\n</ul>\n<p><strong>Mały przykład dla intuicji:</strong></p>\n<p>Dla n=10 sprawdźmy każdą liczbę:</p>\n<ul>\n<li>1 → NWD(1,10)=1 ✓</li>\n<li>2 → NWD(2,10)=2 ✗ (dzieli się przez 2)</li>\n<li>3 → NWD(3,10)=1 ✓</li>\n<li>4 → NWD(4,10)=2 ✗</li>\n<li>5 → NWD(5,10)=5 ✗</li>\n<li>6 → NWD(6,10)=2 ✗</li>\n<li>7 → NWD(7,10)=1 ✓</li>\n<li>8 → NWD(8,10)=2 ✗</li>\n<li>9 → NWD(9,10)=1 ✓</li>\n</ul>\n<p><strong>Wynik:</strong> liczby względnie pierwsze z 10 to {1,3,7,9}, czyli φ(10) = 4</p>\n<h3><a href=\"#dlaczego-φn--p-1--q-1\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-φn--p-1--q-1\"></a>Dlaczego φ(n) = (p-1) × (q-1)?</h3>\n<p>To właśnie <strong>piękno liczb pierwszych</strong>!</p>\n<p>Gdy n = p × q (gdzie p i q to liczby pierwsze), istnieje elegancki wzór:</p>\n<p>Dla liczby pierwszej p, <strong>wszystkie</strong> liczby od 1 do p-1 są z nią względnie pierwsze.\nWięc φ(p) = p-1.</p>\n<p>Dzięki właściwościom mnożenia:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">φ(p × q) = φ(p) × φ(q) = (p-1) × (q-1)\n</code></pre>\n<p><strong>W naszym przykładzie:</strong></p>\n<ul>\n<li>p = 61, więc φ(61) = 60</li>\n<li>q = 53, więc φ(53) = 52</li>\n<li>φ(3233) = 60 × 52 = 3120</li>\n</ul>\n<h3><a href=\"#dlaczego-to-jest-takie-ważne-dla-rsa\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-to-jest-takie-ważne-dla-rsa\"></a>Dlaczego to jest TAKIE ważne dla RSA?</h3>\n<p>Funkcja φ(n) jest <strong>kluczem do klucza prywatnego</strong>!</p>\n<ul>\n<li>Znając p i q → łatwo obliczyć φ(n) → łatwo obliczyć klucz prywatny d</li>\n<li>Znając tylko n → musisz rozłożyć na czynniki → praktycznie niemożliwe dla dużych liczb</li>\n</ul>\n<p>To właśnie ta „sekretna wiedza&quot; o φ(n) pozwala nam stworzyć klucz prywatny, którego nikt inny nie może obliczyć!</p>\n<hr />\n<h2><a href=\"#wybór-wykładnika-publicznego-e\" aria-hidden=\"true\" class=\"anchor\" id=\"wybór-wykładnika-publicznego-e\"></a>Wybór wykładnika publicznego (e)</h2>\n<p>Wybieramy liczbę <code>e</code>, która:</p>\n<ul>\n<li>jest względnie pierwsza z <code>φ(n)</code> (czyli NWD(e, φ(n)) = 1)</li>\n<li>zazwyczaj jest <strong>mała</strong> – to przyspiesza szyfrowanie!</li>\n</ul>\n<h3><a href=\"#dlaczego-65537-jest-tak-popularne\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-65537-jest-tak-popularne\"></a>Dlaczego 65537 jest tak popularne?</h3>\n<p>W praktyce najczęściej używane wartości to:</p>\n<ul>\n<li><strong>3</strong> – najszybsze szyfrowanie, ale może być podatne na niektóre ataki</li>\n<li><strong>17</strong> – dobry kompromis</li>\n<li><strong>65537 (0x10001)</strong> – <strong>standard przemysłowy</strong></li>\n</ul>\n<p><strong>Czemu akurat 65537?</strong></p>\n<p>To liczba Fermata: F₄ = 2^16 + 1 = 65537</p>\n<p>W zapisie binarnym:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">65537 = 10000000000000001 (tylko dwie jedynki!)\n</code></pre>\n<p>To oznacza, że operacja <code>m^65537</code> to tylko:</p>\n<ul>\n<li>16 operacji podniesienia do kwadratu</li>\n<li>1 mnożenie</li>\n</ul>\n<div class=\"markdown-alert markdown-alert-tip\">\n<p class=\"markdown-alert-title\">Dlaczego 65537 to standard?</p>\n<p>Bardzo szybko się liczy (tylko dwie jedynki w zapisie binarnym), a jednocześnie jest wystarczająco duże żeby być bezpieczne. To idealny kompromis między wydajnością a bezpieczeństwem!</p>\n</div>\n<h3><a href=\"#dla-naszego-przykładu\" aria-hidden=\"true\" class=\"anchor\" id=\"dla-naszego-przykładu\"></a>Dla naszego przykładu:</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">e = 17\n</code></pre>\n<p>I teraz mamy:</p>\n<ul>\n<li><strong>klucz publiczny</strong> = <code>(e, n)</code> → <code>(17, 3233)</code></li>\n</ul>\n<p><strong>Uwaga:</strong> nie każde e będzie działać! Musi być względnie pierwsze z φ(n).\nJeśli spróbujesz użyć e, które ma wspólny dzielnik z φ(n), nie da się obliczyć klucza prywatnego d.</p>\n<hr />\n<h2><a href=\"#klucz-prywatny--czyli-to-czego-nie-wolno-zgubić\" aria-hidden=\"true\" class=\"anchor\" id=\"klucz-prywatny--czyli-to-czego-nie-wolno-zgubić\"></a>Klucz prywatny – czyli to, czego nie wolno zgubić</h2>\n<p>Teraz najważniejsze: liczymy <code>d</code>, czyli <strong>odwrotność modularną</strong>:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">d ≡ e⁻¹ (mod φ(n))\n</code></pre>\n<p>Czyli szukamy takiego <code>d</code>, żeby:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">(d * e) % φ(n) = 1\n</code></pre>\n<h3><a href=\"#co-to-właściwie-znaczy\" aria-hidden=\"true\" class=\"anchor\" id=\"co-to-właściwie-znaczy\"></a>Co to właściwie znaczy?</h3>\n<p>Mówimy, że <code>d</code> jest odwrotnością modularną <code>e</code> względem φ(n), gdy ich iloczyn daje resztę 1 po podzieleniu przez φ(n).</p>\n<p><strong>Przykład prostszy:</strong> dla φ(n) = 10 i e = 3</p>\n<ul>\n<li>Szukamy d takiego, że (3 * d) mod 10 = 1</li>\n<li>Sprawdzamy: 3<em>1=3, 3</em>2=6, 3<em>3=9, 3</em>4=12, 3<em>5=15, 3</em>6=18, 3*7=21</li>\n<li>21 mod 10 = 1 ✓ Więc d = 7</li>\n</ul>\n<h3><a href=\"#jak-to-obliczyć-dla-dużych-liczb\" aria-hidden=\"true\" class=\"anchor\" id=\"jak-to-obliczyć-dla-dużych-liczb\"></a>Jak to obliczyć dla dużych liczb?</h3>\n<p>Dla małych liczb możemy próbować po kolei, ale dla liczb 1024-bitowych?\nUżylibyśmy <strong>rozszerzonego algorytmu Euklidesa</strong> (Extended Euclidean Algorithm).</p>\n<details>\n<summary>🔍 Jak działa rozszerzony algorytm Euklidesa?</summary>\n<p>Algorytm znajduje odwrotność modularną w czasie O(log n):</p>\n<p><strong>Krok po kroku:</strong></p>\n<ol>\n<li>Szukamy liczb x, y takich że: <code>e·x + φ(n)·y = NWD(e, φ(n))</code></li>\n<li>Jeśli NWD = 1, to x jest odwrotnością modularną</li>\n<li>Normalizujemy: <code>d = x mod φ(n)</code></li>\n</ol>\n<p><strong>Przykład dla e=17, φ(n)=3120:</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">3120 = 17 × 183 + 9\n17 = 9 × 1 + 8\n9 = 8 × 1 + 1    &lt;- NWD = 1 ✓\n8 = 1 × 8 + 0\n\nWsteczna substytucja:\n1 = 9 - 8\n1 = 9 - (17 - 9) = 2×9 - 17\n1 = 2×(3120 - 183×17) - 17\n1 = 2×3120 - 367×17\n\nWięc: 17 × (-367) ≡ 1 (mod 3120)\nd = -367 mod 3120 = 2753 ✓\n</code></pre>\n<p>To skomplikowane, ale na szczęście biblioteki robią to za nas!</p>\n</details>\n<p>Na szczęście w Pythonie to proste:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-python\"><a-v>d</a-v> <a-o>=</a-o> <a-f>pow</a-f>(<a-v>e</a-v>, <a-o>-</a-o><a-n>1</a-n>, <a-v>phi</a-v>)  <a-c># od Pythona 3.8</a-c></code></pre>\n<p><strong>W naszym przypadku:</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">e = 17\nφ(n) = 3120\nd = 2753\n\nSprawdzenie: (17 * 2753) % 3120 = 46801 % 3120 = 1 ✓\n</code></pre>\n<p>I voilà:</p>\n<ul>\n<li><strong>klucz prywatny</strong> = <code>(d, n)</code> → <code>(2753, 3233)</code></li>\n</ul>\n<div class=\"markdown-alert markdown-alert-important\">\n<p class=\"markdown-alert-title\">Bezpieczeństwo klucza prywatnego</p>\n<p>Klucz prywatny <code>d</code> trzymasz <strong>TYLKO dla siebie</strong>.\nJeśli ktoś go zdobędzie = game over, może odczytać wszystkie twoje wiadomości!</p>\n</div>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-mermaid\">flowchart TB\n    subgraph PUBLIC[&quot;🌍 PUBLICZNE&quot;]\n        E[e = 17&lt;br/&gt;wykładnik publiczny]\n        N[n = 3233&lt;br/&gt;moduł]\n    end\n\n    subgraph SECRET[&quot;🔒 TAJNE&quot;]\n        D[d = 2753&lt;br/&gt;wykładnik prywatny]\n    end\n\n    subgraph TOPSECRET[&quot;🔥 SUPER TAJNE&quot;]\n        P[p = 61&lt;br/&gt;pierwsza liczba pierwsza]\n        Q[q = 53&lt;br/&gt;druga liczba pierwsza]\n        PHI[φ'n' = 3120&lt;br/&gt;funkcja Eulera]\n    end\n\n    TOPSECRET -.-&gt;|generuje| SECRET\n    TOPSECRET -.-&gt;|generuje| PUBLIC\n\n    Note1[&quot;🌍 Wszyscy mogą znać&lt;br/&gt;Publikowane w certyfikatach&quot;]\n    Note2[&quot;🔒 Tylko właściciel&lt;br/&gt;Nigdy nie ujawniaj!&quot;]\n    Note3[&quot;🔥 Zniszczyć po generowaniu kluczy!&lt;br/&gt;⚠️ Jeśli ktoś zna p, q lub φ(n)&lt;br/&gt;może obliczyć d i złamać szyfrowanie&quot;]\n\n    PUBLIC -.-&gt; Note1\n    SECRET -.-&gt; Note2\n    TOPSECRET -.-&gt; Note3\n\n    style PUBLIC fill:#e7f3ff,stroke:#0066cc,stroke-width:2px\n    style SECRET fill:#fff4e6,stroke:#ff9800,stroke-width:3px\n    style TOPSECRET fill:#ffe6e6,stroke:#dc3545,stroke-width:4px,padding:20px,min-width:400px\n    style Note1 fill:#e7f3ff,stroke:#0066cc,stroke-width:2px\n    style Note2 fill:#fff4e6,stroke:#ff9800,stroke-width:2px\n    style Note3 fill:#ffe6e6,stroke:#dc3545,stroke-width:2px\n\n    style E fill:#cce5ff,stroke:#0066cc\n    style N fill:#cce5ff,stroke:#0066cc\n    style D fill:#ffe4cc,stroke:#ff9800\n    style P fill:#ffcccc,stroke:#dc3545\n    style Q fill:#ffcccc,stroke:#dc3545\n    style PHI fill:#ffcccc,stroke:#dc3545\n</code></pre>\n<hr />\n<h2><a href=\"#szyfrowanie--w-końcu\" aria-hidden=\"true\" class=\"anchor\" id=\"szyfrowanie--w-końcu\"></a>Szyfrowanie – w końcu!</h2>\n<h3><a href=\"#jak-zaszyfrować-tekst\" aria-hidden=\"true\" class=\"anchor\" id=\"jak-zaszyfrować-tekst\"></a>Jak zaszyfrować tekst?</h3>\n<p>RSA szyfruje liczby, więc najpierw <strong>konwertujemy tekst na liczby</strong>.</p>\n<p>Najprościej: używamy kodów ASCII!</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">'H' → 72\n'E' → 69\n'L' → 76\n'L' → 76\n'O' → 79\n</code></pre>\n<p>Potem każdą liczbę szyfrujemy osobno wzorem:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">c = m^e mod n\n</code></pre>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-mermaid\">sequenceDiagram\n    autonumber\n    participant A as Alice\n    participant B as Bob\n    participant S as 🌍 Świat&lt;br/&gt;(podsłuchujący)\n\n    Note over B: Generowanie kluczy RSA\n    B-&gt;&gt;B: Wybierz p=61, q=53\n    B-&gt;&gt;B: Oblicz n = 61×53 = 3233\n    B-&gt;&gt;B: Oblicz φ(n) = 60×52 = 3120\n    B-&gt;&gt;B: Wybierz e = 17\n    B-&gt;&gt;B: Oblicz d = 2753\n\n    Note over B: Klucz publiczny: (e=17, n=3233)&lt;br/&gt;Klucz prywatny: (d=2753, n=3233)\n\n    B-&gt;&gt;A: Publikuje klucz publiczny (17, 3233)\n    B-&gt;&gt;S: Publikuje klucz publiczny (17, 3233)\n\n    Note over A: Alice ma wiadomość &quot;HI&quot;\n    A-&gt;&gt;A: Konwersja ASCII: H=72, I=73\n\n    Note over A: Szyfrowanie każdej litery\n    A-&gt;&gt;A: c₁ = 72^17 mod 3233 = 3000\n    A-&gt;&gt;A: c₂ = 73^17 mod 3233 = 1486\n\n    A-&gt;&gt;B: Wysyła [3000, 1486]\n    A-&gt;&gt;S: 👀 Świat widzi [3000, 1486]\n\n    Note over S: ❌ Bez klucza prywatnego d&lt;br/&gt;NIE może odszyfrować!\n\n    Note over B: Deszyfrowanie kluczem prywatnym\n    B-&gt;&gt;B: m₁ = 3000^2753 mod 3233 = 72\n    B-&gt;&gt;B: m₂ = 1486^2753 mod 3233 = 73\n    B-&gt;&gt;B: Konwersja ASCII: 72='H', 73='I'\n\n    Note over B: ✅ Bob odczytał &quot;HI&quot;\n</code></pre>\n<p><strong>Przykład krok po kroku:</strong></p>\n<p>Chcę zaszyfrować słowo <strong>&quot;HI&quot;</strong>:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">1. 'H' → ASCII: 72\n   c₁ = 72^17 mod 3233 = 3000\n\n2. 'I' → ASCII: 73\n   c₂ = 73^17 mod 3233 = 1486\n</code></pre>\n<p>Zaszyfrowana wiadomość: <strong>[3000, 1486]</strong></p>\n<p>Wysyłasz te liczby do odbiorcy. Każdy może je zobaczyć, ale <strong>bez klucza prywatnego nie odszyfrują</strong> ;-)</p>\n<h3><a href=\"#przykład-z-pojedynczą-liczbą\" aria-hidden=\"true\" class=\"anchor\" id=\"przykład-z-pojedynczą-liczbą\"></a>Przykład z pojedynczą liczbą:</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">m = 123\nc = 123^17 mod 3233 = 855\n</code></pre>\n<p>Proste? Proste! Ale <strong>tylko</strong> z kluczem prywatnym możesz to odwrócić.</p>\n<hr />\n<h2><a href=\"#deszyfrowanie\" aria-hidden=\"true\" class=\"anchor\" id=\"deszyfrowanie\"></a>Deszyfrowanie</h2>\n<p>Odbiorca bierze swój klucz prywatny i liczy:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">m = c^d mod n\n</code></pre>\n<p>Dla naszego przykładu z &quot;HI&quot;:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">1. c₁ = 3000\n   m₁ = 3000^2753 mod 3233 = 72 → 'H'\n\n2. c₂ = 1486\n   m₂ = 1486^2753 mod 3233 = 73 → 'I'\n</code></pre>\n<p>Odzyskaliśmy tekst: <strong>&quot;HI&quot;</strong></p>\n<p>Magia? Nie. Matematyka :-)</p>\n<hr />\n<h2><a href=\"#a-jak-to-przesłać-przez-internet-base64-do-akcji\" aria-hidden=\"true\" class=\"anchor\" id=\"a-jak-to-przesłać-przez-internet-base64-do-akcji\"></a>A jak to przesłać przez Internet? Base64 do akcji!</h2>\n<p>OK, mamy zaszyfrowaną wiadomość: <strong>[3000, 1486]</strong></p>\n<p>Ale jak to wysłać mailem, przez API, w JSON-ie? Te liczby mogą być <strong>OGROMNE</strong> (setki cyfr dla prawdziwego RSA).</p>\n<h3><a href=\"#problem\" aria-hidden=\"true\" class=\"anchor\" id=\"problem\"></a>Problem:</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">Zaszyfrowana wiadomość dla 2048-bit RSA:\n[18446744073709551615, 98765432109876543210987654321...]\n</code></pre>\n<p>To niewygodne i może sprawiać problemy przy transmisji.</p>\n<h3><a href=\"#rozwiązanie-base64\" aria-hidden=\"true\" class=\"anchor\" id=\"rozwiązanie-base64\"></a>Rozwiązanie: Base64</h3>\n<p><strong>Base64</strong> to sposób kodowania danych binarnych jako tekst (używając tylko 64 znaków: A-Z, a-z, 0-9, +, /).</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-mermaid\">flowchart TD\n    Start([📝 START: Tekst 'HI'])\n\n    Start --&gt; ASCII[Konwersja ASCII&lt;br/&gt;'H' → 72&lt;br/&gt;'I' → 73]\n\n    ASCII --&gt; RSA[Szyfrowanie RSA&lt;br/&gt;c₁ = 72^17 mod 3233 = 3000&lt;br/&gt;c₂ = 73^17 mod 3233 = 1486]\n\n    RSA --&gt; HEX[Konwersja do hexadecimal&lt;br/&gt;3000₁₀ = 0x0BB8&lt;br/&gt;1486₁₀ = 0x05CE]\n\n    HEX --&gt; BYTES[Bajty: 0B B8 05 CE&lt;br/&gt;'4 bajty razem']\n\n    BYTES --&gt; BIN[Binary:&lt;br/&gt;00001011 10111000 00000101 11001110]\n\n    BIN --&gt; GROUP[Grupowanie po 6 bitów&lt;br/&gt;000010 111011 100000 000101 110011 10----]\n\n    GROUP --&gt; PAD[Dopełnienie zerami ostatniej grupy&lt;br/&gt;000010 111011 100000 000101 110011 100000]\n\n    PAD --&gt; CONV[Konwersja do znaków base64&lt;br/&gt;000010→C, 111011→7, 100000→g&lt;br/&gt;000101→F, 110011→z, 100000→g]\n\n    CONV --&gt; PADDING{Padding?&lt;br/&gt;4 bajty = niepełny blok}\n\n    PADDING --&gt;|Dodaj '==' dla wyrównania| RESULT[✅ Wynik: 'C7gFzg==']\n\n    RESULT --&gt; End([🌐 Gotowe do wysłania!])\n\n    Info[💡 Base64 używa tylko 64 znaków:&lt;br/&gt;A-Z, a-z, 0-9, +, /&lt;br/&gt;Bezpieczne dla każdego protokołu!]\n\n    RESULT -.-&gt; Info\n\n    style Start fill:#e1f5ff,stroke:#0066cc,stroke-width:3px\n    style RESULT fill:#d4edda,stroke:#28a745,stroke-width:3px\n    style End fill:#d4edda,stroke:#28a745,stroke-width:3px\n    style PADDING fill:#fff3cd,stroke:#ffc107,stroke-width:2px\n    style Info fill:#f0f0f0,stroke:#6c757d,stroke-width:2px\n    style RSA fill:#ffe6e6,stroke:#dc3545,stroke-width:2px\n</code></pre>\n<p><strong>Proces krok po kroku:</strong></p>\n<h3><a href=\"#przykład-dla-hi\" aria-hidden=\"true\" class=\"anchor\" id=\"przykład-dla-hi\"></a>Przykład dla &quot;HI&quot;:</h3>\n<p>Mamy zaszyfrowaną wiadomość: <strong>[3000, 1486]</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">Krok 1: Konwertuj każdą liczbę na bajty (hexadecimal)\n   3000 (decimal) = 0x0BB8 = [0B B8] (2 bajty)\n   1486 (decimal) = 0x05CE = [05 CE] (2 bajty)\n\nKrok 2: Połącz wszystkie bajty w jeden ciąg\n   [0B B8 05 CE] (4 bajty razem)\n\nKrok 3: Bajty → base64\n   Bajty:    0B    B8    05    CE\n   Binary:   00001011 10111000 00000101 11001110\n\n   Grupujemy po 6 bitów (base64 używa 6-bitowych grup):\n   000010 111011 100000 000101 110011 10\n\n   Dopełniamy ostatnią grupę zerami:\n   000010 111011 100000 000101 110011 100000\n\n   Konwertujemy każdą 6-bitową grupę na znak base64:\n   000010 → C\n   111011 → 7\n   100000 → g\n   000101 → F\n   110011 → z\n   100000 → g\n\n   Dodajemy padding (==) bo base64 pracuje w 3-bajtowych blokach:\n   - 4 bajty = 3 bajty (pełny blok) + 1 bajt (niepełny)\n   - 1 bajt → 2 znaki + '==' (padding do pełnego bloku)\n   &quot;C7gFzg==&quot;\n</code></pre>\n<p><strong>Podsumowanie dla &quot;HI&quot;:</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">Oryginał:       &quot;HI&quot;\nASCII:          [72, 73]\nZaszyfrowane:   [3000, 1486]\nBajty (hex):    [0B B8 05 CE]\nBase64:         &quot;C7gFzg==&quot;\n</code></pre>\n<p>Teraz możesz wysłać <strong>&quot;C7gFzg==&quot;</strong> przez e-mail, JSON, gdziekolwiek!</p>\n<p>Odbiorca robi proces odwrotny:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">&quot;C7gFzg==&quot; → [0B B8 05 CE] → [3000, 1486] → deszyfruj → [72, 73] → &quot;HI&quot;\n</code></pre>\n<h3><a href=\"#dlaczego-to-ważne\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-to-ważne\"></a>Dlaczego to ważne?</h3>\n<ul>\n<li><strong>Kompaktowe</strong> – krótszy zapis niż surowe liczby</li>\n<li><strong>Bezpieczne</strong> – działa w każdym systemie (nie ma problemów z kodowaniem)</li>\n<li><strong>Uniwersalne</strong> – standard używany wszędzie (certyfikaty PEM, JWT, itp.)</li>\n</ul>\n<p><strong>W praktyce:</strong> większość bibliotek kryptograficznych automatycznie używa base64 do przesyłania zaszyfrowanych danych.</p>\n<hr />\n<h2><a href=\"#dlaczego-to-jest-bezpieczne\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-to-jest-bezpieczne\"></a>Dlaczego to jest bezpieczne?</h2>\n<p>Pierwsze pytanie dla ciebie:\n<strong>co byś musiał zrobić, żeby złamać RSA?</strong></p>\n<p>Ano… rozłożyć <code>n</code> na czynniki pierwsze (<code>p</code> i <code>q</code>).\nDla małych liczb – luz.\nDla liczb 2048-bitowych? Powodzenia, serio ;-)</p>\n<p>Całe bezpieczeństwo RSA opiera się na tym, że:</p>\n<blockquote>\n<p><strong>mnożyć jest łatwo, rozkładać – piekielnie trudno</strong></p>\n</blockquote>\n<h3><a href=\"#ale-czekaj--skąd-się-biorą-te-duże-liczby-pierwsze\" aria-hidden=\"true\" class=\"anchor\" id=\"ale-czekaj--skąd-się-biorą-te-duże-liczby-pierwsze\"></a>Ale czekaj – skąd się biorą te duże liczby pierwsze?</h3>\n<p>To dobre pytanie! Nie możemy przecież wypisać wszystkich liczb pierwszych i wybrać dwie – dla 1024 bitów byłoby ich <strong>astronomicznie dużo</strong>.</p>\n<p><strong>Rozwiązanie:</strong> losowanie + test pierwszości</p>\n<p><strong>Algorytm generowania liczby pierwszej:</strong></p>\n<ol>\n<li>Wylosuj dużą liczbę nieparzystą (np. 1024-bitową)</li>\n<li>Wykonaj test pierwszości (np. Miller-Rabin z 40 rundami)</li>\n<li>Jeśli test przeszedł → mamy liczbę pierwszą ✓</li>\n<li>Jeśli test nie przeszedł → dodaj 2 i testuj ponownie</li>\n<li>Powtarzaj aż znajdziesz pierwszą</li>\n</ol>\n<p><strong>Ile to trwa?</strong></p>\n<p>Według twierdzenia o liczbach pierwszych, prawdopodobieństwo że losowa liczba ~n jest pierwsza to <strong>≈ 1 / ln(n)</strong>.\nDla liczb 1024-bitowych: średnio trzeba sprawdzić <strong>~355 liczb</strong> żeby trafić na pierwszą.</p>\n<p>Na współczesnym komputerze? <strong>Kilka sekund</strong> do minuty.</p>\n<h4><a href=\"#test-millera-rabina\" aria-hidden=\"true\" class=\"anchor\" id=\"test-millera-rabina\"></a>Test Millera-Rabina</h4>\n<p>To najpopularniejszy test pierwszości w kryptografii:</p>\n<ul>\n<li><strong>probabilistyczny</strong> – nie daje 100% pewności, ale możemy ją dowolnie zwiększać</li>\n<li><strong>szybki</strong> – O(k log³ n), gdzie k to liczba rund</li>\n<li>po 40 rundach: prawdopodobieństwo błędu &lt; 2⁻⁸⁰ (praktycznie pewność!)</li>\n</ul>\n<p>W praktyce działa tak:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">dla każdej rundy:\n    wylosuj liczbę 'a'\n    sprawdź matematyczne własności n\n    jeśli test nie przejdzie → n NIE jest pierwsza\n\njeśli wszystkie testy przeszły → n jest prawdopodobnie pierwsza\n</code></pre>\n<details>\n<summary>🔍 Matematyka za testem Millera-Rabina</summary>\n<p>Test wykorzystuje <strong>małe twierdzenie Fermata</strong> i własności pierwiastków pierwotnych:</p>\n<p><strong>Dla liczby pierwszej n:</strong></p>\n<ol>\n<li>Zapisz: <code>n - 1 = 2^r × d</code> (gdzie d nieparzyste)</li>\n<li>Wybierz losowe <code>a</code> z zakresu [2, n-2]</li>\n<li>Oblicz: <code>x = a^d mod n</code></li>\n<li>Sprawdź:\n<ul>\n<li>Jeśli <code>x = 1</code> lub <code>x = n-1</code> → możliwe, że pierwsza</li>\n<li>Powtórz <code>r-1</code> razy: <code>x = x² mod n</code></li>\n<li>Jeśli któreś <code>x = n-1</code> → możliwe, że pierwsza</li>\n<li>W przeciwnym razie → <strong>na pewno złożona</strong></li>\n</ul>\n</li>\n</ol>\n<p><strong>Przykład dla n=221:</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">221 - 1 = 220 = 4 × 55 = 2² × 55\nr=2, d=55\n\nLosujemy a=174:\nx = 174^55 mod 221 = 47\n47 ≠ 1 i 47 ≠ 220\n\nx = 47² mod 221 = 168\n168 ≠ 220\n\nTest nie przeszedł → 221 jest złożone! ✓\n(Faktycznie: 221 = 13 × 17)\n</code></pre>\n<p>Kluczowa własność: liczba złożona ma <strong>maksymalnie 25% szans</strong> oszukania testu w jednej rundzie. Po 40 rundach szansa: (0.25)^40 ≈ 10⁻²⁴ – praktycznie niemożliwe!</p>\n</details>\n<h3><a href=\"#o-czym-trzeba-pamiętać-przy-implementacji\" aria-hidden=\"true\" class=\"anchor\" id=\"o-czym-trzeba-pamiętać-przy-implementacji\"></a>O czym trzeba pamiętać przy implementacji?</h3>\n<h4><a href=\"#1-źródło-losowości-ma-znaczenie\" aria-hidden=\"true\" class=\"anchor\" id=\"1-źródło-losowości-ma-znaczenie\"></a>1. Źródło losowości ma znaczenie!</h4>\n<p>Są dwa podejścia do generowania liczb losowych:</p>\n<p><strong>Pseudolosowe generatory (np. Mersenne Twister):</strong></p>\n<ul>\n<li>szybkie</li>\n<li><strong>ale przewidywalne!</strong> – jeśli ktoś zgadnie lub pozna seed, może odtworzyć twoje klucze</li>\n<li>⚠️ <strong>NIGDY w produkcji!</strong></li>\n</ul>\n<p><strong>Kryptograficznie bezpieczne generatory:</strong></p>\n<ul>\n<li>używają entropii z systemu operacyjnego (<code>/dev/urandom</code>, sprzętowe RNG)</li>\n<li><strong>nieprzewidywalne</strong> nawet znając poprzednie wartości</li>\n<li>nieco wolniejsze</li>\n<li>✅ <strong>jedyna opcja do prawdziwych kluczy</strong></li>\n</ul>\n<div class=\"markdown-alert markdown-alert-warning\">\n<p class=\"markdown-alert-title\">Słaba losowość = katastrofa bezpieczeństwa</p>\n<p>W 2012 roku grupa badaczy znalazła <strong>12 tysięcy</strong> publicznych kluczy RSA w internecie, które dzieliły wspólne czynniki pierwsze. Dlaczego? Słaba losowość przy generowaniu!\n<strong>Zawsze używaj kryptograficznie bezpiecznych generatorów losowych!</strong></p>\n</div>\n<h4><a href=\"#2-padding-jest-krytyczny\" aria-hidden=\"true\" class=\"anchor\" id=\"2-padding-jest-krytyczny\"></a>2. Padding jest krytyczny</h4>\n<p>Podstawowy RSA (o którym piszę) to tzw. <strong>&quot;textbook RSA&quot;</strong> – działa, ale ma problemy:</p>\n<p><strong>Problem deterministyczny:</strong></p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">encrypt(&quot;TAK&quot;) zawsze daje ten sam wynik\nencrypt(&quot;NIE&quot;) zawsze daje ten sam wynik\n</code></pre>\n<p>Atakujący może zgadywać wiadomości i porównywać wyniki!</p>\n<p><strong>Rozwiązanie:</strong> OAEP (Optimal Asymmetric Encryption Padding)</p>\n<ul>\n<li>dodaje losowość do każdego szyfrowania</li>\n<li>ta sama wiadomość za każdym razem daje <strong>inny</strong> szyfrogram</li>\n<li>dodatkowo chroni przed innymi atakami</li>\n</ul>\n<div class=\"markdown-alert markdown-alert-warning\">\n<p class=\"markdown-alert-title\">Nigdy nie używaj &quot;textbook RSA&quot; w produkcji!</p>\n<p>Podstawowy RSA bez paddingu jest <strong>podatny na ataki</strong>. Zawsze używaj OAEP lub innego sprawdzonego schematu paddingu. To nie jest opcjonalne – to wymóg bezpieczeństwa!</p>\n</div>\n<h4><a href=\"#3-timing-attacks--bo-czas-też-gada\" aria-hidden=\"true\" class=\"anchor\" id=\"3-timing-attacks--bo-czas-też-gada\"></a>3. Timing attacks – bo czas też gada</h4>\n<p>Operacja <code>m = c^d mod n</code> trwa różnie długo w zależności od bitów w <code>d</code>.</p>\n<p>Atakujący mierząc <strong>czas deszyfrowania</strong> tysięcy wiadomości może <strong>odtworzyć klucz prywatny</strong>!</p>\n<p><strong>Obrona:</strong></p>\n<ul>\n<li>operacje w stałym czasie (constant-time algorithms)</li>\n<li>blinding – losowe przekształcenie przed deszyfrowaniem</li>\n</ul>\n<div class=\"markdown-alert markdown-alert-warning\">\n<p class=\"markdown-alert-title\">Nie implementuj kryptografii sam!</p>\n<p>Timing attacks to tylko jeden z wielu zagrożeń. <strong>Używaj sprawdzonych bibliotek</strong> kryptograficznych (OpenSSL, libsodium, itd.) zamiast pisać własne implementacje. Eksperci spędzili lata chroniąc te biblioteki przed atakami!</p>\n</div>\n<hr />\n<h2><a href=\"#jak-duże-powinny-być-klucze-w-praktyce\" aria-hidden=\"true\" class=\"anchor\" id=\"jak-duże-powinny-być-klucze-w-praktyce\"></a>Jak duże powinny być klucze w praktyce?</h2>\n<p>W naszym przykładzie używałem małych liczb (p=61, q=53), ale w rzeczywistości...</p>\n<h3><a href=\"#rozmiary-kluczy-i-bezpieczeństwo\" aria-hidden=\"true\" class=\"anchor\" id=\"rozmiary-kluczy-i-bezpieczeństwo\"></a>Rozmiary kluczy i bezpieczeństwo</h3>\n<table>\n<thead>\n<tr>\n<th>Rozmiar klucza</th>\n<th>Status</th>\n<th>Szacowany czas złamania</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>512 bitów</strong></td>\n<td>❌ Niezabezpieczone</td>\n<td>Złamane w 1999 (RSA-155)</td>\n</tr>\n<tr>\n<td><strong>768 bitów</strong></td>\n<td>❌ Niezabezpieczone</td>\n<td>Złamane w 2009 (RSA-768, 2000 CPU-lat)<sup class=\"footnote-ref\"><a href=\"#fn-2\" id=\"fnref-2\" data-footnote-ref>2</a></sup></td>\n</tr>\n<tr>\n<td><strong>1024 bity</strong></td>\n<td>⚠️ Przestarzałe</td>\n<td>Możliwe dla dużych organizacji</td>\n</tr>\n<tr>\n<td><strong>2048 bitów</strong></td>\n<td>✅ <strong>Minimum dzisiaj</strong></td>\n<td>Bezpieczne do ~2030</td>\n</tr>\n<tr>\n<td><strong>3072 bity</strong></td>\n<td>✅ Zalecane</td>\n<td>Długoterminowe bezpieczeństwo</td>\n</tr>\n<tr>\n<td><strong>4096 bitów</strong></td>\n<td>✅ Bardzo bezpieczne</td>\n<td>Paranoja level ;-)</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Konkretnie:</strong> dla 2048-bitowego klucza każda liczba pierwsza (p i q) ma <strong>~1024 bity = ~309 cyfr dziesiętnych</strong>.</p>\n<p>Przykładowa taka liczba:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">179769313486231590772930519078902473361797697894230657273430081157732675805\n500963132708477322407536021120113879871393357658789768814416622492847430639\n474124377767893424865485276302219601246094119453082952085005768838150682342\n462881473913110540827237163350510684586298239947245938479716304835356329624\n224137217\n</code></pre>\n<p>Rozłożenie takiej liczby na czynniki? Z obecną technologią: <strong>niemożliwe</strong> w rozsądnym czasie.</p>\n<h3><a href=\"#a-co-z-komputerami-kwantowymi\" aria-hidden=\"true\" class=\"anchor\" id=\"a-co-z-komputerami-kwantowymi\"></a>A co z komputerami kwantowymi?</h3>\n<p>Tutaj sprawa się robi ciekawa...</p>\n<p>Algorytm Shora (kwantowy) teoretycznie może <strong>złamać RSA w czasie wielomianowym</strong>.</p>\n<p><strong>Dzisiaj:</strong></p>\n<ul>\n<li>komputery kwantowe są za słabe (mamy ~100 qubitów, potrzeba tysięcy stabilnych)</li>\n<li>RSA jest bezpieczne</li>\n</ul>\n<p><strong>Za 10-20 lat?</strong></p>\n<ul>\n<li>możliwe że RSA stanie się podatne</li>\n<li>dlatego już teraz rozwija się <strong>kryptografia post-kwantowa</strong> (np. CRYSTALS-Kyber, Dilithium)</li>\n</ul>\n<div class=\"markdown-alert markdown-alert-caution\">\n<p class=\"markdown-alert-title\">Zagrożenie kwantowe</p>\n<p>Komputery kwantowe mogą złamać RSA w czasie wielomianowym (algorytm Shora). Choć dziś są za słabe, za 10-20 lat mogą stać się realnym zagrożeniem.\n<strong>Przygotuj się:</strong> NIST standaryzuje już algorytmy post-kwantowe<sup class=\"footnote-ref\"><a href=\"#fn-3\" id=\"fnref-3\" data-footnote-ref>3</a></sup>. Dla długoterminowego bezpieczeństwa rozważ algorytmy odporne na komputery kwantowe (CRYSTALS-Kyber, Dilithium).</p>\n</div>\n<hr />\n<h2><a href=\"#formaty-kluczy--jak-to-wygląda-w-praktyce\" aria-hidden=\"true\" class=\"anchor\" id=\"formaty-kluczy--jak-to-wygląda-w-praktyce\"></a>Formaty kluczy – jak to wygląda w praktyce?</h2>\n<p>Klucze RSA możesz zapisać na różne sposoby:</p>\n<h3><a href=\"#pem-privacy-enhanced-mail\" aria-hidden=\"true\" class=\"anchor\" id=\"pem-privacy-enhanced-mail\"></a>PEM (Privacy Enhanced Mail)</h3>\n<p>To najpopularniejszy format, wyglądający tak:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">-----BEGIN RSA PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo\n4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u\n...\n-----END RSA PUBLIC KEY-----\n</code></pre>\n<p>Format base64 + nagłówki. Uniwersalny, działa wszędzie.</p>\n<h3><a href=\"#der-distinguished-encoding-rules\" aria-hidden=\"true\" class=\"anchor\" id=\"der-distinguished-encoding-rules\"></a>DER (Distinguished Encoding Rules)</h3>\n<p>Binarna wersja PEM – mniejsza, szybsza do parsowania, ale nieczytelna dla człowieka.</p>\n<h3><a href=\"#json-web-key-jwk\" aria-hidden=\"true\" class=\"anchor\" id=\"json-web-key-jwk\"></a>JSON Web Key (JWK)</h3>\n<p>Dla aplikacji webowych:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-json\">{\n  <a-s>&quot;kty&quot;</a-s>: <a-s>&quot;RSA&quot;</a-s>,\n  <a-s>&quot;n&quot;</a-s>: <a-s>&quot;u1SU1LfVLPHCozMxH2Mo...&quot;</a-s>,\n  <a-s>&quot;e&quot;</a-s>: <a-s>&quot;AQAB&quot;</a-s>\n}</code></pre>\n<p>Łatwo używać w API, JavaScript, itd.</p>\n<hr />\n<h2><a href=\"#gdzie-spotykasz-rsa-na-co-dzień\" aria-hidden=\"true\" class=\"anchor\" id=\"gdzie-spotykasz-rsa-na-co-dzień\"></a>Gdzie spotykasz RSA na co dzień?</h2>\n<p>Jeśli korzystasz z:</p>\n<ul>\n<li><strong>HTTPS</strong> 🔒 – certyfikaty SSL/TLS używają RSA (albo nowszych ECDSA)</li>\n<li><strong>SSH</strong> – <code>ssh-keygen</code> domyślnie generuje klucze RSA</li>\n<li><strong>podpisy cyfrowe</strong> – pliki .exe na Windowsie, dokumenty PDF</li>\n<li><strong>e-mail</strong> – PGP/GPG do szyfrowania maili</li>\n<li><strong>VPN</strong> – tunele szyfrowane</li>\n</ul>\n<p>…to tak, <strong>RSA tam siedzi</strong> i robi robotę.</p>\n<h3><a href=\"#ciekawostka-podpisy-cyfrowe\" aria-hidden=\"true\" class=\"anchor\" id=\"ciekawostka-podpisy-cyfrowe\"></a>Ciekawostka: podpisy cyfrowe</h3>\n<p>RSA działa też w drugą stronę!</p>\n<p><strong>Szyfrowanie:</strong> klucz publiczny → szyfruj, klucz prywatny → deszyfruj\n<strong>Podpis cyfrowy:</strong> klucz prywatny → podpisz, klucz publiczny → zweryfikuj</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">podpis = hash(wiadomość)^d mod n\nweryfikacja = podpis^e mod n == hash(wiadomość)\n</code></pre>\n<p>Dzięki temu możesz udowodnić, że TO TY napisałeś daną wiadomość (bo tylko ty masz klucz prywatny).</p>\n<hr />\n<h2><a href=\"#przypisy\" aria-hidden=\"true\" class=\"anchor\" id=\"przypisy\"></a>Przypisy</h2>\n<section class=\"footnotes\" data-footnotes>\n<ol>\n<li id=\"fn-1\">\n<p>RSA pochodzi od nazwisk trzech twórców: <strong>R</strong>on <strong>R</strong>ivest, <strong>A</strong>di <strong>S</strong>hamir i Leonard <strong>A</strong>dleman, którzy opublikowali algorytm w 1977 roku. Ciekawostka: brytyjski matematyk Clifford Cocks wynalazł podobny system kilka lat wcześniej (1973), ale jego praca była tajna! <a href=\"#fnref-1\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"1\" aria-label=\"Back to reference 1\">↩</a></p>\n</li>\n<li id=\"fn-2\">\n<p>RSA-768 (232 cyfry dziesiętne) zostało złamane w 2009 roku przez międzynarodowy zespół badaczy. Projekt wymagał około 2000 lat czasu CPU na komputerach z tamtego okresu. To pokazuje, że rozmiar klucza ma <strong>kluczowe</strong> znaczenie dla bezpieczeństwa. <a href=\"#fnref-2\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"2\" aria-label=\"Back to reference 2\">↩</a></p>\n</li>\n<li id=\"fn-3\">\n<p>W 2024 roku NIST (National Institute of Standards and Technology) opublikował pierwsze standardy kryptografii post-kwantowej: FIPS 203 (ML-KEM, wcześniej CRYSTALS-Kyber), FIPS 204 (ML-DSA, wcześniej CRYSTALS-Dilithium) i FIPS 205 (SLH-DSA, wcześniej SPHINCS+). To algorytmy odporne na ataki komputerów kwantowych. <a href=\"#fnref-3\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"3\" aria-label=\"Back to reference 3\">↩</a></p>\n</li>\n</ol>\n</section>\n",
      "summary": "",
      "date_published": "2025-12-18T00:00:00-00:00",
      "image": "",
      "authors": [
        {
          "name": "Błażej Gruszka",
          "url": "https://www.linkedin.com/in/blazejgruszka/",
          "avatar": "https://github.com/bgruszka.png"
        }
      ],
      "tags": [
        "rsa",
        "cryptography",
        "security",
        "encryption",
        "algorithms"
      ],
      "language": "pl"
    },
    {
      "id": "https://gruszka.dev/red-metrics.html",
      "url": "https://gruszka.dev/red-metrics.html",
      "title": "Metryki RED – prosty sposób na zrozumienie zdrowia systemu",
      "content_html": "<p>Monitorowanie systemów rozproszonych, mikroserwisów czy aplikacji webowych może wydawać się trudne. W praktyce jednak nie zawsze potrzebujemy zaawansowanych, skomplikowanych narzędzi – czasami wystarczy prosty model, który pomoże nam ocenić, czy wszystko działa jak należy.</p>\n<p>Jednym z takich modeli są metryki RED:</p>\n<ul>\n<li>Rate – liczba żądań na sekundę</li>\n<li>Errors – liczba błędów na sekundę</li>\n<li>Duration – czas trwania żądań</li>\n</ul>\n<p>Brzmi prosto? Bo takie właśnie ma być 🙂</p>\n<h2><a href=\"#rate--ile-żądań-przetwarza-twój-system\" aria-hidden=\"true\" class=\"anchor\" id=\"rate--ile-żądań-przetwarza-twój-system\"></a>Rate – ile żądań przetwarza twój system</h2>\n<p>Pierwsza metryka mówi nam, jak bardzo &quot;obciążony&quot; jest system. To po prostu tempo obsługi żądań.</p>\n<p>Możesz na przykład sprawdzić:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-bash\"><a-f>requests_per_second</a-f> = total_requests / observation_time</code></pre>\n<p>Dlaczego to ważne?</p>\n<ul>\n<li>pozwala zauważyć skoki ruchu,</li>\n<li>ułatwia planowanie pojemności systemu,</li>\n<li>pokazuje, czy system w ogóle przyjmuje żądania (bo jeśli tempo nagle spada do zera, to mamy problem 😉).</li>\n</ul>\n<h2><a href=\"#errors--jakie-błędy-pojawiają-się-w-systemie\" aria-hidden=\"true\" class=\"anchor\" id=\"errors--jakie-błędy-pojawiają-się-w-systemie\"></a>Errors – jakie błędy pojawiają się w systemie</h2>\n<p>Nie wystarczy wiedzieć, ile żądań trafia do aplikacji – trzeba też wiedzieć, ile z nich kończy się niepowodzeniem.</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-bash\"><a-f>error_rate</a-f> = failed_requests / total_requests</code></pre>\n<p>Monitorując błędy, zwróć uwagę na:</p>\n<ul>\n<li>nagłe skoki błędów 5xx (problem po stronie serwera),</li>\n<li>błędy 4xx (np. niepoprawne dane wejściowe),</li>\n<li>nietypowe kody statusu, które mogą oznaczać problemy w logice aplikacji.</li>\n</ul>\n<p>Dzięki tej metryce bardzo szybko dowiesz się, czy system działa poprawnie – nawet jeśli nadal odpowiada na żądania.</p>\n<h2><a href=\"#duration--ile-trwa-obsługa-żądania\" aria-hidden=\"true\" class=\"anchor\" id=\"duration--ile-trwa-obsługa-żądania\"></a>Duration – ile trwa obsługa żądania</h2>\n<p>Trzecia metryka dotyczy czasu reakcji. Użytkownik może nie zauważyć, że serwer obsłużył milion żądań – ale na pewno zauważy, jeśli każda strona ładuje się 5 sekund.</p>\n<p>Dlatego mierzymy:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-bash\"><a-f>avg_duration</a-f> = total_time / total_requests</code></pre>\n<p>Możesz też śledzić percentyle (np. P95, P99), żeby zobaczyć, jak wygląda doświadczenie większości użytkowników, a nie tylko średnia.</p>\n<h2><a href=\"#dlaczego-red-działa-tak-dobrze\" aria-hidden=\"true\" class=\"anchor\" id=\"dlaczego-red-działa-tak-dobrze\"></a>Dlaczego RED działa tak dobrze?</h2>\n<p>Bo te trzy proste metryki wystarczą, żeby odpowiedzieć na kluczowe pytania:</p>\n<ul>\n<li>czy mój system działa? (Rate)</li>\n<li>czy działa poprawnie? (Errors)</li>\n<li>czy działa wystarczająco szybko? (Duration)</li>\n</ul>\n<p>Nie potrzebujesz od razu setek wskaźników ani skomplikowanych dashboardów – wystarczy RED jako podstawa monitoringu.</p>\n<p>Jak widzisz, metryki RED są proste i jednocześnie skuteczne 🙂\nJeśli wprowadzisz je do swojego systemu, będziesz miał zawsze jasny obraz tego, co się dzieje – niezależnie od tego, jak skomplikowana jest twoja architektura.</p>\n",
      "summary": "",
      "date_published": "2025-09-19T00:00:00-00:00",
      "image": "",
      "authors": [
        {
          "name": "Błażej Gruszka",
          "url": "https://www.linkedin.com/in/blazejgruszka/",
          "avatar": "https://github.com/bgruszka.png"
        }
      ],
      "tags": [
        "metrics",
        "devops",
        "observability"
      ],
      "language": "pl"
    }
  ]
}