EntityFrameworkCore.Encryption - self-promo

Trochu self-promo, ale…

Počas prvej vlny pandemických dobrovoľníckych projektov som si všimol, že mnohí skladujú rodné čísla a zdravotné záznamy len tak. Bonusom bola autentifikácia, kde sa s frontednu posielal hash hesla, ktorý sa porovnával priamo v databáze.

Veľmi dlho sa mi páči myšlienka Always Encrypted v MS SQL. Táto funkcionalita umožňuje mať v databáze zašifrované dáta tak, že ich nevidí ani databázový administrátor ani nik okoloidúci, lebo si ich rozšifruje priamo aplikácia cez MS SQL klienta. No daná technológia nie je ľahko použiteľná v prípade, že ako zdroj šifrovacích kľúčov je niečo iné ako Azure Key Valut, alebo certifikát vo Windows store.

Po narazení na blog Jiřího Činčuri som začal pracovať na knižnici, ktorá pridá funkcionalitu „Alwais encrypted“ priamo do Entity Frameworkového modelu modelu – Harrison314.EntityFrameworkCore.Encryption.

Táto knižnica je postavená na EF Value konvertoroch, takže šifrovanie je s pohľadu aplikácie transparentné. No prácu so zašifrovanými stĺpcami je možná len v „encryption scope“ (v podstate sa tak označia časti programu, ktoré majú prístup k šifrovaným dátam).

Kľúčové vlastnosti:

  • Databázovo agnostický
  • Inšpirované MS SQL Always Encrypted (obdobná kryptografia, algoritmy, deterministické a randomizované šifrovanie riadkov v tabuľke,…)
  • Podpora kompresie dát
  • KillSwitch (Encryption provider vie signalizovať, že treba okamžite zmazať šifrovacie kľúče z pamäte a vypnúť aplikáciu)
  • Rôzny provideri pre šifrovanie databázového master kľúča:
    • Heslo
    • Certifikát v store
    • Čipová karta (dá sa zlomiť, keď na dvere zaklopú kukláči), HSM
    • DPAPI
    • Vlastné provideri, sieťový provideri,…

Malá ukážka kódu:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Patient>(p =>
        {
            p.HasKey(t => t.Id);
            p.Property(t => t.FirstName).IsRequired().HasMaxLength(150);
            p.Property(t => t.LastName).IsRequired().HasMaxLength(150);
            p.Property(t => t.SocialSecurityNumber).IsRequired().HasMaxLength(150);
            // ...
        });

        modelBuilder.Entity<Visist>(p =>
        {
            p.HasKey(t => t.Id);
        });
    }

Pre použitie šifrovaných stĺpcov v tabuľke stačí priďať:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.AddEncryptionContext();

        modelBuilder.Entity<Patient>(p =>
        {
            p.HasKey(t => t.Id);
            p.Property(t => t.FirstName)
              .HasEncrypted("Patient.FirstName", 
                  EncrypetionType.AEAD_AES_256_CBC_HMAC_SHA_256,
                  EncryptionMode.Randomized,
                  CompressionMode.None)
              .IsRequired().HasMaxLength(150);
            p.Property(t => t.LastName)
              .HasEncrypted("Patient.LastName",
                  EncrypetionType.AEAD_AES_256_CBC_HMAC_SHA_256,
                  EncryptionMode.Randomized,
                  CompressionMode.None)
              .IsRequired().HasMaxLength(150);
            p.Property(t => t.SocialSecurityNumber)
              .HasEncrypted("Patient.SocialSecurityNumber",
                  EncrypetionType.AEAD_AES_256_CBC_HMAC_SHA_256,
                  EncryptionMode.Deterministic,
                  CompressionMode.None)
              .IsRequired().HasMaxLength(150);
            // ...
        });

        modelBuilder.Entity<Visist>(p =>
        {
            p.HasKey(t => t.Id);
        });
    }

Plus registrovať služby a šifrovacieho providera v IoC kontaineri.
Viac informácii a ukážky kódu sú na githubej stránke projektu https://github.com/harrison314/Harrison314.EntityFrameworkCore.Encryption.

1 Like

Ako je to potom s vecmi ako je sort? toto je šifrovanie na strane db a teda to vie zohľadniť?

Toto je sifrovanie na strane klienta, len s pohladu kodu a doptov sa EF tvari, ze programator pracuje so nezasifrovanymi datami.

Sort, LIKE, porovnavanie to nepodporuje, zasifrovany stlpec (a to len v Deteministickom mode) je mozne porovnavat na presnu zhodu. Rovnake je to pouzitim MS SQL Always Encrypted.

Takato technologia nie je na to, aby sa zasifrovala cela databaza, ale len velmi citlive casti (napriklad cisla platobnych kariet, rodne cislo, atd…).

Sifrovanie na strane databazy vie aj sort, fulltext, Like,… lebo sa sifruju datove stranky pri zapise na disk.
Len to musi podporovat databazovy stroj (napr v MS SQL Transparent Data Encryption (TDE) - SQL Server | Microsoft Docs). Ale to chrani napriklad pred kradezou diskou alebo unikom zaloh. No data v databaze vidi administrator systemu.