Przejdź do treści

Anonimizacja z kluczem publicznym i prywatnym

Ten przykład dodaje szyfrowanie kluczem publicznym RSA i odtwarzanie kluczem prywatnym do bezstanowej anonimizacji odwracalnej. RSA-3072 OAEP-SHA256 szyfruje nowy klucz AES-256-GCM dla każdego tokenu. Osobny klucz uwierzytelniania wystawcy, wyprowadzony z istniejącego lokalnego zbioru kluczy, uwierzytelnia całą kopertę przed odszyfrowaniem RSA. Implementacja korzysta z mechanizmów RSA i AEAD biblioteki cryptography.

Nie powstaje baza konwersacji ani mapowanie jawnymi wartościami. Weryfikacja tokenu pozostaje związana z zaufanym tenantem, tożsamością, odciskiem aktywnej reguły i terminem ważności. Stabilne identyfikatory w danym zakresie rozpoznają jednakowe wartości oryginalne; zaszyfrowane tokeny nadal są losowane.

1. Wygeneruj klucze raz

Po zainstalowaniu FastFence i rozpakowaniu archiwum przykładów do examples/ wykonaj w katalogu instalacji:

uv tool run --python 3.12 [email protected] init --anonymization
uv run --python 3.12 --no-project --with fastfence==1.0.1 python examples/asymmetric_keys.py

Pierwsze polecenie tworzy prywatny zbiór kluczy wystawcy, jeśli go brakuje. Drugie tworzy state/private/anonymization-rsa/public.pem i private.pem z uprawnieniami 0600. Odmawia nadpisania któregokolwiek pliku. Ponowne wykonanie nie jest poleceniem rotacji kluczy.

Kompletny wykonywalny generator kluczy jest osadzony bezpośrednio ze źródła:

"""Generate an RSA-3072 recipient pair without overwriting any existing file."""

import argparse
import os
from pathlib import Path

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa


def generate_pair(directory: Path) -> tuple[Path, Path]:
    directory.mkdir(parents=True, exist_ok=True, mode=0o700)
    public_path = directory / "public.pem"
    private_path = directory / "private.pem"
    if public_path.exists() or private_path.exists():
        raise FileExistsError("Refusing to overwrite an existing RSA key pair")
    private = rsa.generate_private_key(public_exponent=65537, key_size=3072)
    values = (
        (
            private_path,
            private.private_bytes(
                serialization.Encoding.PEM,
                serialization.PrivateFormat.PKCS8,
                serialization.NoEncryption(),
            ),
        ),
        (
            public_path,
            private.public_key().public_bytes(
                serialization.Encoding.PEM,
                serialization.PublicFormat.SubjectPublicKeyInfo,
            ),
        ),
    )
    created = []
    try:
        for path, data in values:
            descriptor = os.open(
                path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600
            )
            created.append(path)
            with os.fdopen(descriptor, "wb") as stream:
                stream.write(data)
                stream.flush()
                os.fsync(stream.fileno())
    except OSError:
        for path in created:
            path.unlink(missing_ok=True)
        raise
    return public_path, private_path


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--directory",
        type=Path,
        default=Path("state/private/anonymization-rsa"),
    )
    args = parser.parse_args()
    try:
        public, private = generate_pair(args.directory)
    except OSError as error:
        raise SystemExit(f"Key generation failed: {error}") from None
    print(f"Public encryption key: {public}")
    print(f"Private recovery key: {private}")
    print(
        "Keep private.pem and the issuer keyring private; neither belongs in Git."
    )


if __name__ == "__main__":
    main()

Pobierz asymmetric_keys.py · Zobacz źródło

2. Skonfiguruj bramkę

Ustaw obie ścieżki w powłoce uruchamiającej FastFence lub dodaj te ustawienia do własnego .env:

export FASTFENCE_ANONYMIZATION_PUBLIC_KEY_FILE=state/private/anonymization-rsa/public.pem
export FASTFENCE_ANONYMIZATION_PRIVATE_KEY_FILE=state/private/anonymization-rsa/private.pem
uv tool run --python 3.12 [email protected] doctor
uv tool run --python 3.12 [email protected] serve

Względne ścieżki RSA są rozwiązywane względem FASTFENCE_ROOT (domyślnie katalog roboczy). Oba pliki PEM muszą opisywać tę samą parę RSA-3072 z wykładnikiem publicznym 65537. Istniejący zbiór kluczy wystawcy state/anonymization-keys.json nadal jest wymagany: samo szyfrowanie kluczem publicznym nie uwierzytelnia wystawcy tokenu i nie tworzy stabilnych aliasów opartych na kluczu.

Klucze są ładowane raz podczas startu. Po zmianie ustawień kluczy uruchom bramkę ponownie. Pełna bramka wymaga klucza prywatnego nawet przy wyłączonym przywracaniu odpowiedzi, ponieważ wewnętrznie odszyfrowuje otrzymane tokeny do kontroli zgodnie z aktualnymi zasadami. Nie zaimplementowano bramki przekazującej tylko z kluczem publicznym ani trybu odzyskiwania z kluczem wyłącznie po stronie klienta.

Przechowuj private.pem i zbiór kluczy wystawcy prywatnie, poza Git. Publiczny PEM można udostępniać jako publiczny klucz szyfrowania; samo jego posiadanie nie pozwala stworzyć podrobionego tokenu akceptowanego przez FastFence.

3. Włącz regułę odwracalną

W Policies → Add anonymization rule ustaw dopasowanie literalne, np. Anna Kowalska, etykietę zamiennika PERSON i właściwy zakres wejścia/wyjścia oraz modelu/narzędzia. Zezwól na jawne przywracanie, jeśli chcesz udostępnić tę opcję. Przejrzyj konfigurację kandydata i przed aktywacją ustaw tryb odzyskiwania Reversible w formularzu ustawień.

Poniżej znajduje się odpowiednia sekcja polityki. Dołącz ją do pełnej polityki zamiast zastępować cały plik:

anonymization:
  enabled: true
  mode: reversible
  rules:
    - id: person
      operator: literal
      value: Anna Kowalska
      replacement: PERSON
      direction: both
      target: all
      allow_restore: true

Po skonfigurowaniu pary RSA nowe tokeny odwracalne zaczynają się od [FFR2.. Dotychczasowe symetryczne tokeny [FFR1. pozostają weryfikowalne, dopóki dostępny jest ich klucz wystawcy i pasująca reguła oraz nie upłynęła ważność. Zachowanie nieodwracalnych [FFI1. pozostaje bez zmian.

4. Sprawdź wejście i wyjście

Użyj przykładu chronionego żądania lub Test requests, aby wysłać tekst objęty regułą. Przy wyłączonym przywracaniu model otrzymuje token, a odpowiedź zachowuje chronioną postać wartości. Przy restore_originals: true w żądaniu i allow_restore: true w regule bramka może odtworzyć kompletne poprawne tokeny w dostarczanej odpowiedzi.

Model może pominąć lub zmienić tokeny. FastFence nie odtwarza niepełnego szyfrogramu i nie zgaduje brakującej wartości oryginalnej. Po przywróceniu nadal obowiązują kontrole prywatności i blokowania wyjścia; uprawnienie do przywracania ich nie zastępuje.

Czas życia kluczy i wydajność

Ta implementacja ładuje jedną parę RSA odbiorcy. Jej wymiana uniemożliwia odczyt wcześniejszych tokenów FFR2, nawet jeśli zbiór kluczy wystawcy zachowuje stare klucze wystawcy. Zachowaj pierwotną parę przez wymagany okres odzyskiwania albo poczekaj na wygaśnięcie tokenów przed zmianą; automatyczna rotacja wielu odbiorców nie jest zaimplementowana. Usunięcie klucza wystawcy unieważnia także tokeny nim uwierzytelnione.

Koperty RSA dodają bajty i operacje asymetryczne względem tokenów symetrycznych. Konfiguracja jest odczytywana tylko przy starcie, ale ten tryb nie ma deklarowanej latencji równej lokalnemu dopasowaniu literalnemu. Nadal obowiązują ograniczenia długości tokenu i wartości, rozmiaru żądania oraz liczby zamian; zbyt duże wartości są odrzucane.