CodeGym /Kursy /SQL SELF /Przykłady szyfrowania danych na poziomie tabel i kolumn

Przykłady szyfrowania danych na poziomie tabel i kolumn

SQL SELF
Poziom 48 , Lekcja 2
Dostępny

Informacje trzymane w bazie danych często mają mega dużą wartość dla firmy. Niestety, są też łakomym kąskiem dla różnych złych ludzi. Dlatego warto pomyśleć o szyfrowaniu — to jeden ze sposobów, żeby chronić dane przed niepowołanymi osobami.

Szyfrowanie pomaga zabezpieczyć poufne info: na przykład hasła, numery kart kredytowych czy dane osobowe. Dodatkowo, pomaga spełnić wymagania różnych przepisów, jak GDPR czy HIPAA. A jeśli dojdzie do wycieku, zaszyfrowane dane są dużo mniej podatne na atak, więc potencjalne szkody są mniejsze.

W PostgreSQL masz wygodne funkcje do szyfrowania symetrycznego. Dzięki pgp_sym_encrypt(data, key) możesz zaszyfrować dane, a potem odszyfrować je za pomocą pgp_sym_decrypt(encrypted_data, key), używając tego samego klucza. Prosto i bezpiecznie.

Przykład szyfrowania danych

Krok 1: Tworzenie tabeli

Stwórzmy tabelę users z kolumną, która będzie trzymać zaszyfrowane numery telefonów:

-- Tworzenie tabeli z kolumną na zaszyfrowane dane
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username TEXT NOT NULL,
    phone_encrypted BYTEA -- Tu będą trzymane zaszyfrowane numery telefonów
);

Krok 2: Dodawanie danych z szyfrowaniem

Teraz dodajemy użytkownika, szyfrując jego numer telefonu:

-- Wstawianie danych z szyfrowaniem
INSERT INTO users (username, phone_encrypted)
VALUES ('john_doe', pgp_sym_encrypt('123-456-7890', 'my_secret_key'));

Zwróć uwagę na użycie funkcji pgp_sym_encrypt. my_secret_key — to nasz klucz symetryczny. W realu klucz powinien być trudny do zgadnięcia i dobrze zabezpieczony.

Krok 3: Pobieranie danych z deszyfrowaniem

Kiedy trzeba dostać się do danych, możemy je odszyfrować:

-- Pobieranie danych z deszyfrowaniem
SELECT 
    username, 
    pgp_sym_decrypt(phone_encrypted, 'my_secret_key') AS phone
FROM users;

Jeśli klucz jest poprawny, zobaczysz oryginalny numer telefonu.

Wyższy poziom: dodawanie szyfrowania do istniejącej tabeli

A co jeśli tabela już istnieje i chcemy zacząć szyfrować dane w jednej z jej kolumn? Zobaczmy przykład.

Krok 1: Tworzenie nowej kolumny

Załóżmy, że mamy tabelę customers i chcemy zaszyfrować kolumny z numerami kart kredytowych:

-- Dodawanie nowej kolumny na zaszyfrowane dane
ALTER TABLE customers ADD COLUMN card_number_encrypted BYTEA;

Krok 2: Przenoszenie danych do zaszyfrowanej kolumny

Szyfrujemy istniejące dane i wrzucamy je do nowej kolumny:

-- Szyfrowanie danych i przenoszenie do nowej kolumny
UPDATE customers
SET card_number_encrypted = pgp_sym_encrypt(card_number, 'my_other_secret_key');

Krok 3: Usuwanie niezaszyfrowanej kolumny

Po udanym szyfrowaniu starej kolumny można się pozbyć:

-- Usuwanie starej niezaszyfrowanej kolumny
ALTER TABLE customers DROP COLUMN card_number;

Teraz dane są chronione szyfrowaniem i dostęp do nich jest możliwy tylko z kluczem.

Specyfika pracy z zaszyfrowanymi danymi

Jest kilka ważnych rzeczy przy pracy z zaszyfrowanymi kolumnami:

Typ danych:

  • Zaszyfrowane wartości są trzymane w formacie binarnym (BYTEA), a nie jako czytelny tekst.
  • Przy zapytaniach trzeba używać funkcji deszyfrujących.

Wyszukiwanie i filtrowanie:

  • Nie da się bezpośrednio szukać po zaszyfrowanych danych, np.:
  SELECT * FROM users WHERE phone_encrypted = '123-456-7890'; -- NIE ZADZIAŁA!
  • Zamiast tego można odszyfrować dane w zapytaniu:
  SELECT *
  FROM users
  WHERE pgp_sym_decrypt(phone_encrypted, 'my_secret_key') = '123-456-7890';

Wydajność:

Szyfrowanie i deszyfrowanie danych może spowalniać zapytania. Używaj tego tylko tam, gdzie naprawdę trzeba.

Prawdziwy scenariusz: ochrona haseł

Przechowywanie haseł to jeden z najczęstszych przypadków użycia szyfrowania. Zamiast trzymać hasła w otwartym tekście (zły pomysł), trzeba je hashować.

Hashowanie hasła z użyciem pgcrypto

Użyjemy funkcji crypt() do bezpiecznego hashowania haseł:

-- Hashowanie hasła przy wstawianiu rekordu
INSERT INTO users (username, phone_encrypted)
VALUES ('alice', crypt('moje_bezpieczne_haslo', gen_salt('bf')));

Tutaj gen_salt('bf') generuje sól do hashowania hasła.

Żeby sprawdzić hasło, porównujemy jego hash:

-- Porównanie zhashowanego hasła
SELECT username
FROM users
WHERE crypt('moje_bezpieczne_haslo', phone_encrypted) = phone_encrypted;

Porady dotyczące bezpieczeństwa

  1. Trzymaj klucze osobno:

Nigdy nie zapisuj kluczy symetrycznych w tej samej bazie co zaszyfrowane dane.

  1. Używaj trudnych kluczy:

Proste klucze, jak "123", łatwo zgadnąć.

  1. Regularnie zmieniaj klucze:

Żeby zapobiec wyciekom danych, warto co jakiś czas zmieniać klucze i przeszifrować dane.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION