Основи криптографії¶
Що таке криптографія?¶
Криптографія — це наука про захист інформації за допомогою математичних алгоритмів. Вона забезпечує:
- Конфіденційність — тільки авторизовані особи можуть прочитати дані
- Цілісність — дані не були змінені
- Автентичність — підтвердження особи відправника
- Неспростовність — відправник не може заперечити відправлення
┌─────────────────────────────────────────────────────────────────┐
│ Plaintext ────▶ [Encrypt] ────▶ Ciphertext ────▶ [Decrypt] ──▶│
│ "Hello" ↑ "x7Gh2k" ↑ │
│ │ │ │
│ Key Key │
│ │
│ Тільки хто має правильний ключ може розшифрувати │
└─────────────────────────────────────────────────────────────────┘
Симетричне шифрування¶
Принцип роботи¶
Один ключ для шифрування та дешифрування.
┌─────────────────────────────────────────────────────────────────┐
│ Alice Bob │
│ │
│ Plaintext: "Secret" │
│ │ │
│ ▼ Encrypt(key="password123") │
│ Ciphertext: "x7Gh2kL9..." │
│ │ │
│ │ ═══════════ передача ═══════════▶ │
│ │ │ │
│ │ ▼ │
│ │ Decrypt(key="password123") │
│ │ │ │
│ │ ▼ │
│ │ Plaintext: "Secret" │
│ │
│ Проблема: Як безпечно передати ключ? │
└─────────────────────────────────────────────────────────────────┘
Алгоритми¶
| Алгоритм | Розмір ключа | Статус | Примітки |
|---|---|---|---|
| DES | 56 біт | Небезпечний | Не використовувати! |
| 3DES | 168 біт | Застарілий | Повільний |
| AES-128 | 128 біт | Безпечний | Стандарт |
| AES-256 | 256 біт | Дуже безпечний | Рекомендовано |
| ChaCha20 | 256 біт | Безпечний | Швидкий на CPU без AES-NI |
Режими шифрування (Block Cipher Modes)¶
┌─────────────────────────────────────────────────────────────────┐
│ ECB (Electronic Codebook) — НЕ ВИКОРИСТОВУВАТИ! │
│ │
│ Однакові блоки → однаковий шифротекст │
│ [Block1] → [EncB1] │
│ [Block1] → [EncB1] ← той самий! │
│ [Block2] → [EncB2] │
│ │
│ Видно паттерни в даних! │
├─────────────────────────────────────────────────────────────────┤
│ CBC (Cipher Block Chaining) — краще │
│ │
│ IV ─────────▶ XOR ─▶ [Encrypt] ─▶ Ciphertext1 ──┐ │
│ [Block1] ────┘ │ │
│ ▼ │
│ [Block2] ─────────▶ XOR ─▶ [Encrypt] ─▶ Ciphertext2 │
│ │
│ Потребує IV (Initialization Vector), послідовне │
├─────────────────────────────────────────────────────────────────┤
│ GCM (Galois/Counter Mode) — РЕКОМЕНДОВАНО │
│ │
│ • Authenticated encryption (шифрування + цілісність) │
│ • Паралельне шифрування (швидко) │
│ • Включає authentication tag │
│ │
│ AES-256-GCM — gold standard │
└─────────────────────────────────────────────────────────────────┘
Приклад з OpenSSL¶
# Шифрування файлу з AES-256-CBC
openssl enc -aes-256-cbc -salt -pbkdf2 -in secret.txt -out secret.enc
# Запитає пароль
# Дешифрування
openssl enc -aes-256-cbc -d -pbkdf2 -in secret.enc -out decrypted.txt
# AES-256-GCM (рекомендовано)
openssl enc -aes-256-gcm -salt -pbkdf2 -in file.txt -out file.enc
Асиметричне шифрування¶
Принцип роботи¶
Пара ключів: публічний (public) та приватний (private).
┌─────────────────────────────────────────────────────────────────┐
│ Key Pair Generation: │
│ │
│ [Generate] ──▶ Public Key (можна поширювати) │
│ └▶ Private Key (ЗБЕРІГАТИ В СЕКРЕТІ!) │
│ │
├─────────────────────────────────────────────────────────────────┤
│ Шифрування: │
│ │
│ Alice хоче надіслати повідомлення Bob: │
│ │
│ 1. Bob публікує свій Public Key │
│ 2. Alice шифрує: Encrypt(message, Bob's Public Key) │
│ 3. Тільки Bob може розшифрувати своїм Private Key │
│ │
│ "Публічний ключ — замок, приватний — ключ від замка" │
└─────────────────────────────────────────────────────────────────┘
Алгоритми¶
| Алгоритм | Тип | Розмір ключа | Використання |
|---|---|---|---|
| RSA | Шифрування + підпис | 2048-4096 біт | TLS, SSH, GPG |
| ECDSA | Підпис | 256-384 біт | TLS, Bitcoin |
| Ed25519 | Підпис | 256 біт | SSH, сучасний стандарт |
| X25519 | Key exchange | 256 біт | TLS 1.3 |
RSA¶
┌─────────────────────────────────────────────────────────────────┐
│ RSA — найпоширеніший алгоритм │
│ │
│ Безпека базується на складності факторизації великих чисел │
│ │
│ n = p × q (де p, q — великі прості числа) │
│ │
│ Знаючи n, дуже важко знайти p і q │
│ │
│ Рекомендовані розміри: │
│ • 2048 біт — мінімум │
│ • 3072 біт — рекомендовано │
│ • 4096 біт — для довгострокового захисту │
└─────────────────────────────────────────────────────────────────┘
Ed25519¶
┌─────────────────────────────────────────────────────────────────┐
│ Ed25519 — сучасний алгоритм підпису │
│ │
│ Переваги: │
│ • Коротші ключі (256 біт ≈ RSA 3000 біт) │
│ • Швидший за RSA │
│ • Захищений від timing attacks │
│ • Простіша реалізація (менше помилок) │
│ │
│ Рекомендовано для SSH: │
│ ssh-keygen -t ed25519 │
└─────────────────────────────────────────────────────────────────┘
Приклад з OpenSSL¶
# Генерація RSA ключів
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -out public.pem
# Шифрування публічним ключем
openssl rsautl -encrypt -inkey public.pem -pubin -in message.txt -out encrypted.bin
# Дешифрування приватним ключем
openssl rsautl -decrypt -inkey private.pem -in encrypted.bin -out decrypted.txt
# Генерація Ed25519 (для SSH)
ssh-keygen -t ed25519 -C "your@email.com"
Хеш-функції¶
Що таке хеш?¶
Хеш-функція перетворює дані будь-якого розміру в фіксований "відбиток".
┌─────────────────────────────────────────────────────────────────┐
│ Властивості криптографічного хешу: │
│ │
│ 1. Детермінований │
│ Однаковий вхід → однаковий хеш (завжди) │
│ │
│ 2. Швидкий │
│ Обчислення займає мілісекунди │
│ │
│ 3. Односторонній │
│ Неможливо відновити вхідні дані з хешу │
│ │
│ 4. Collision resistant │
│ Практично неможливо знайти два різних входи з однаковим │
│ хешем │
│ │
│ 5. Avalanche effect │
│ Маленька зміна входу → повністю інший хеш │
└─────────────────────────────────────────────────────────────────┘
Avalanche Effect¶
$ echo -n "Hello" | sha256sum
185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969
$ echo -n "hello" | sha256sum
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
# Одна буква змінилася — хеш повністю інший!
Алгоритми¶
| Алгоритм | Розмір | Статус | Використання |
|---|---|---|---|
| MD5 | 128 біт | НЕБЕЗПЕЧНИЙ | Тільки checksums |
| SHA-1 | 160 біт | НЕБЕЗПЕЧНИЙ | Не використовувати |
| SHA-256 | 256 біт | Безпечний | Стандарт |
| SHA-384 | 384 біт | Безпечний | Високий рівень |
| SHA-512 | 512 біт | Безпечний | Максимальний рівень |
| SHA-3 | 256/512 біт | Безпечний | Новий стандарт |
| BLAKE2 | 256/512 біт | Безпечний | Швидший за SHA |
Чому MD5 та SHA-1 небезпечні?¶
┌─────────────────────────────────────────────────────────────────┐
│ Collision Attack — знайти два різних файли з однаковим хешем │
│ │
│ MD5: Collision знайдено за секунди (2004) │
│ SHA-1: Collision знайдено (2017, Google "SHAttered") │
│ │
│ Атакуючий може створити підроблений файл з тим самим хешем! │
│ │
│ НІКОЛИ не використовувати для: │
│ • Паролів │
│ • Цифрових підписів │
│ • Сертифікатів │
└─────────────────────────────────────────────────────────────────┘
Приклади з Linux¶
# Обчислити хеш файлу
sha256sum file.txt
# e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file.txt
# Перевірити хеш
echo "e3b0c44298fc1c... file.txt" | sha256sum -c
# file.txt: OK
# Різні алгоритми
md5sum file.txt # НЕ для безпеки!
sha1sum file.txt # Застарілий
sha384sum file.txt
sha512sum file.txt
# OpenSSL
openssl dgst -sha256 file.txt
HMAC (Hash-based Message Authentication Code)¶
HMAC = хеш + секретний ключ = верифікація цілісності та автентичності.
┌─────────────────────────────────────────────────────────────────┐
│ Простий хеш: будь-хто може обчислити │
│ │
│ HMAC: тільки хто знає ключ може обчислити та перевірити │
│ │
│ HMAC(key, message) = hash(key || hash(key || message)) │
│ │
│ Використання: │
│ • API автентифікація │
│ • JWT підпис │
│ • Cookie захист │
└─────────────────────────────────────────────────────────────────┘
# Обчислити HMAC
echo -n "message" | openssl dgst -sha256 -hmac "secretkey"
# SHA256(stdin)= 5c9a4c9fa5f21d3e0a9e8c9f4c3d5b1e...
# В Python
import hmac, hashlib
hmac.new(b"secretkey", b"message", hashlib.sha256).hexdigest()
Цифровий підпис¶
Як працює¶
┌─────────────────────────────────────────────────────────────────┐
│ Підписання (Signing): │
│ │
│ 1. Обчислити хеш документа │
│ 2. Зашифрувати хеш ПРИВАТНИМ ключем = підпис │
│ │
│ Document ──▶ [Hash] ──▶ [Encrypt with Private Key] ──▶ Signature
│ │
├─────────────────────────────────────────────────────────────────┤
│ Верифікація (Verifying): │
│ │
│ 1. Розшифрувати підпис ПУБЛІЧНИМ ключем = хеш │
│ 2. Обчислити хеш документа │
│ 3. Порівняти хеші │
│ │
│ Signature ──▶ [Decrypt with Public Key] ──▶ Hash1 │
│ Document ──▶ [Hash] ──▶ Hash2 │
│ Hash1 == Hash2 ? ✓ Valid : ✗ Invalid │
└─────────────────────────────────────────────────────────────────┘
Приклад з OpenSSL¶
# Генерувати ключі
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# Підписати файл
openssl dgst -sha256 -sign private.pem -out signature.bin document.txt
# Верифікувати підпис
openssl dgst -sha256 -verify public.pem -signature signature.bin document.txt
# Verified OK
GPG підпис¶
# Підписати файл
gpg --sign document.txt # Бінарний підпис
gpg --clearsign document.txt # Текстовий підпис
gpg --detach-sign document.txt # Окремий файл підпису
# Верифікувати
gpg --verify document.txt.sig document.txt
Key Derivation Functions (KDF)¶
Навіщо потрібні?¶
Паролі зазвичай слабкі. KDF роблять їх сильнішими.
┌─────────────────────────────────────────────────────────────────┐
│ Проблема: │
│ Пароль "password123" → легко зламати brute-force │
│ │
│ Рішення: │
│ KDF(password, salt, iterations) → криптографічний ключ │
│ │
│ • Salt — унікальне випадкове значення (запобігає rainbow tables)
│ • Iterations — кількість повторень (уповільнює brute-force) │
│ • Memory — використання RAM (ускладнює GPU атаки) │
└─────────────────────────────────────────────────────────────────┘
Алгоритми¶
| Алгоритм | Тип | Використання |
|---|---|---|
| PBKDF2 | Ітеративний | Legacy, LUKS1 |
| bcrypt | Memory-hard | Паролі (старий стандарт) |
| scrypt | Memory-hard | Паролі, криптовалюти |
| Argon2 | Memory-hard | Рекомендовано |
Argon2 — сучасний стандарт¶
# argon2 приклад (якщо встановлений)
echo -n "password" | argon2 somesalt -t 3 -m 12 -p 1
# В Python
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash("password")
# $argon2id$v=19$m=65536,t=3,p=4$...
# Верифікація
ph.verify(hash, "password") # True
Генерація випадкових чисел¶
CSPRNG (Cryptographically Secure PRNG)¶
┌─────────────────────────────────────────────────────────────────┐
│ Звичайний PRNG (rand(), Math.random()): │
│ • Передбачуваний (якщо знати seed) │
│ • НЕ для криптографії! │
│ │
│ CSPRNG (/dev/urandom, CryptoRandom): │
│ • Непередбачуваний │
│ • Використовує ентропію системи │
│ • Безпечний для криптографії │
└─────────────────────────────────────────────────────────────────┘
Linux¶
# Читати випадкові байти
head -c 32 /dev/urandom | xxd
# Генерувати випадкову строку
openssl rand -hex 32
# або
openssl rand -base64 32
# Генерувати пароль
< /dev/urandom tr -dc 'A-Za-z0-9!@#$%' | head -c 20
Python¶
# Правильно
import secrets
secrets.token_hex(32) # Випадковий hex
secrets.token_urlsafe(32) # URL-safe base64
secrets.randbelow(100) # Випадкове число 0-99
# НЕПРАВИЛЬНО для криптографії!
import random
random.randint(0, 100) # Передбачуваний!
Практичні рекомендації¶
Що використовувати¶
┌─────────────────────────────────────────────────────────────────┐
│ Задача │ Рекомендація │
├──────────────────────────────┼─────────────────────────────────┤
│ Симетричне шифрування │ AES-256-GCM │
│ Асиметричне шифрування │ RSA-4096 або X25519 │
│ Цифровий підпис │ Ed25519 або RSA-4096 │
│ Хешування │ SHA-256 або SHA-3 │
│ Хешування паролів │ Argon2id │
│ HMAC │ HMAC-SHA256 │
│ Key exchange │ X25519 або ECDH │
│ TLS │ TLS 1.3 │
└──────────────────────────────┴─────────────────────────────────┘
Чого уникати¶
┌─────────────────────────────────────────────────────────────────┐
│ НІКОЛИ не використовувати: │
│ │
│ • MD5, SHA-1 для безпеки │
│ • DES, 3DES │
│ • ECB mode │
│ • RC4 │
│ • Власні криптографічні алгоритми │
│ • Hardcoded keys у коді │
│ • rand() для криптографії │
│ • Паролі без salt │
│ • RSA < 2048 біт │
└─────────────────────────────────────────────────────────────────┘
Підсумок¶
| Тип | Алгоритм | Використання |
|---|---|---|
| Симетричне | AES-256-GCM | Шифрування даних |
| Асиметричне | RSA, Ed25519 | TLS, підписи |
| Хеш | SHA-256 | Цілісність |
| KDF | Argon2 | Паролі |
| HMAC | HMAC-SHA256 | Автентифікація |
Головне правило: Використовуйте перевірені бібліотеки, не винаходьте власну криптографію!
Див. також¶
Шлях: security/cryptography-basics.md