Mengonfigurasi Perlindungan Data ASP.NET Core

Ketika sistem Perlindungan Data diinisialisasi, sistem menerapkan pengaturan default berdasarkan lingkungan operasional. Pengaturan ini sesuai untuk aplikasi yang berjalan pada satu komputer. Namun, ada kasus di mana pengembang mungkin ingin mengubah pengaturan default:

  • Aplikasi ini tersebar di beberapa komputer.
  • Untuk alasan kepatuhan.

Untuk skenario ini, sistem Perlindungan Data menawarkan API konfigurasi yang kaya.

Peringatan

Mirip dengan file konfigurasi, cincin kunci perlindungan data harus dilindungi menggunakan izin yang sesuai. Anda dapat memilih untuk mengenkripsi kunci saat tidak aktif, tetapi ini tidak mencegah penyerang membuat kunci baru. Akibatnya, keamanan aplikasi Anda terpengaruh. Lokasi penyimpanan yang dikonfigurasi dengan Perlindungan Data harus memiliki akses terbatas pada aplikasi itu sendiri, mirip dengan cara Anda akan melindungi file konfigurasi. Misalnya, jika Anda memilih untuk menyimpan cincin kunci di disk, gunakan izin sistem file. Pastikan hanya identitas tempat aplikasi web Anda berjalan telah membaca, menulis, dan membuat akses ke direktori tersebut. Jika Anda menggunakan Azure Blob Storage, hanya aplikasi web yang harus memiliki kemampuan untuk membaca, menulis, atau membuat entri baru di penyimpanan blob, dll.

Metode AddDataProtection ekstensi mengembalikan IDataProtectionBuilder. IDataProtectionBuilder mengekspos metode ekstensi yang dapat Anda rantai bersama-sama untuk mengonfigurasi opsi Perlindungan Data.

Paket NuGet berikut diperlukan untuk ekstensi Perlindungan Data yang digunakan dalam artikel ini:

ProtectKeysWithAzureKeyVault

Masuk ke Azure menggunakan CLI, misalnya:

az login

Untuk mengelola kunci dengan Azure Key Vault, konfigurasikan sistem dengan ProtectKeysWithAzureKeyVault di Program.cs. blobUriWithSasToken adalah URI lengkap tempat file kunci harus disimpan. URI harus berisi token SAS sebagai parameter string kueri:

builder.Services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
    .ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());

Agar aplikasi dapat berkomunikasi dan mengotorisasi dirinya sendiri dengan KeyVault, paket Azure.Identity harus ditambahkan.

Atur lokasi penyimpanan cincin kunci (misalnya, PersistKeysToAzureBlobStorage). Lokasi harus diatur karena panggilan ProtectKeysWithAzureKeyVault mengimplementasikan IXmlEncryptor yang menonaktifkan pengaturan perlindungan data otomatis, termasuk lokasi penyimpanan cincin kunci. Contoh sebelumnya menggunakan Azure Blob Storage untuk mempertahankan cincin kunci. Untuk informasi selengkapnya, lihat Penyedia penyimpanan utama: Azure Storage. Anda juga dapat mempertahankan cincin kunci secara lokal dengan PersistKeysToFileSystem.

keyIdentifier adalah pengidentifikasi kunci brankas kunci yang digunakan untuk enkripsi kunci. Misalnya, kunci yang dibuat di brankas kunci bernama dataprotection di contosokeyvault memiliki pengidentifikasi https://contosokeyvault.vault.azure.net/keys/dataprotection/kunci . Berikan izin Get, Unwrap Key, dan Wrap Key ke brankas kunci.

ProtectKeysWithAzureKeyVault kelebihan beban:

Jika aplikasi menggunakan paket Azure yang lebih lama (Microsoft.AspNetCore.DataProtection.AzureStorage dan Microsoft.AspNetCore.DataProtection.AzureKeyVault), sebaiknya hapus referensi ini dan tingkatkan ke Azure.Extensions.AspNetCore.DataProtection.Blobs dan Azure.Extensions.AspNetCore.DataProtection.Keys. Paket-paket ini adalah tempat pembaruan baru disediakan, dan mengatasi beberapa masalah keamanan dan stabilitas utama dengan paket yang lebih lama.

builder.Services.AddDataProtection()
    // This blob must already exist before the application is run
    .PersistKeysToAzureBlobStorage("<storageAccountConnectionString", "<containerName>", "<blobName>")
    // Removing this line below for an initial run will ensure the file is created correctly
    .ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());

PersistKeysToFileSystem

Untuk menyimpan kunci pada berbagi UNC, bukan di lokasi default %LOCALAPPDATA% , konfigurasikan sistem dengan PersistKeysToFileSystem:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));

Peringatan

Jika Anda mengubah lokasi persistensi kunci, sistem tidak lagi secara otomatis mengenkripsi kunci saat tidak aktif, karena tidak tahu apakah DPAPI adalah mekanisme enkripsi yang sesuai.

PersistKeysToDbContext

Untuk menyimpan kunci dalam database menggunakan EntityFramework, konfigurasikan sistem dengan paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :

builder.Services.AddDataProtection()
    .PersistKeysToDbContext<SampleDbContext>();

Kode sebelumnya menyimpan kunci dalam database yang dikonfigurasi. Konteks database yang digunakan harus menerapkan IDataProtectionKeyContext. IDataProtectionKeyContext mengekspos properti DataProtectionKeys

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;

Properti ini mewakili tabel tempat kunci disimpan. Buat tabel secara manual atau dengan DbContext Migrasi. Untuk informasi selengkapnya, lihat DataProtectionKey .

ProtectKeysWith*

Anda dapat mengonfigurasi sistem untuk melindungi kunci saat tidak aktif dengan memanggil salah satu API konfigurasi ProtectKeysWith* . Pertimbangkan contoh di bawah ini, yang menyimpan kunci pada berbagi UNC dan mengenkripsi kunci tersebut saat tidak aktif dengan sertifikat X.509 tertentu:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);

Anda dapat menyediakan X509Certificate2 ke ProtectKeysWithCertificate, seperti sertifikat yang dimuat dari file:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));

Lihat Enkripsi Kunci Saat Istirahat untuk contoh dan diskusi selengkapnya tentang mekanisme enkripsi kunci bawaan.

UnprotectKeysWithAnyCertificate

Anda dapat memutar sertifikat dan mendekripsi kunci saat tidak aktif menggunakan array X509Certificate2 sertifikat dengan UnprotectKeysWithAnyCertificate:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
    .UnprotectKeysWithAnyCertificate(
        new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
        new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));

SetDefaultKeyLifetime

Untuk mengonfigurasi sistem untuk menggunakan masa pakai kunci 14 hari alih-alih default 90 hari, gunakan SetDefaultKeyLifetime:

builder.Services.AddDataProtection()
    .SetDefaultKeyLifetime(TimeSpan.FromDays(14));

SetApplicationName

Secara default, sistem Perlindungan Data mengisolasi aplikasi satu sama lain berdasarkan jalur akar kontennya, bahkan jika mereka berbagi repositori kunci fisik yang sama. Isolasi ini mencegah aplikasi memahami payload yang dilindungi satu sama lain.

Untuk berbagi payload yang dilindungi di antara aplikasi:

  • Konfigurasikan SetApplicationName di setiap aplikasi dengan nilai yang sama.
  • Gunakan versi tumpukan API Perlindungan Data yang sama di seluruh aplikasi. Lakukan salah satu hal berikut dalam file proyek aplikasi:
builder.Services.AddDataProtection()
    .SetApplicationName("<sharedApplicationName>");

SetApplicationName secara internal menetapkan DataProtectionOptions.ApplicationDiscriminator. Untuk tujuan pemecahan masalah, nilai yang ditetapkan ke diskriminator oleh kerangka kerja dapat dicatat dengan kode berikut yang ditempatkan setelah WebApplication dibangun di Program.cs:

var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
    .Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);

Untuk informasi selengkapnya tentang bagaimana diskriminator digunakan, lihat bagian berikut ini nanti di artikel ini:

Peringatan

Di .NET 6, WebApplicationBuilder menormalkan jalur akar konten ke akhir dengan DirectorySeparatorChar. Misalnya, pada Windows jalur akar konten berakhir di \ dan di Linux /. Host lain tidak menormalkan jalur. Sebagian besar aplikasi yang bermigrasi dari HostBuilder atau WebHostBuilder tidak akan berbagi nama aplikasi yang sama karena tidak akan memiliki penghentian DirectorySeparatorChar. Untuk mengatasi masalah ini, hapus karakter pemisah direktori dan atur nama aplikasi secara manual, seperti yang ditunjukkan dalam kode berikut:

using Microsoft.AspNetCore.DataProtection;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);
var trimmedContentRootPath = builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);
builder.Services.AddDataProtection()
 .SetApplicationName(trimmedContentRootPath);
var app = builder.Build();

app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);

app.Run();

DisableAutomaticKeyGeneration

Anda mungkin memiliki skenario di mana Anda tidak ingin aplikasi secara otomatis menggulung kunci (membuat kunci baru) saat mendekati kedaluwarsa. Salah satu contoh skenario ini mungkin adalah aplikasi yang disiapkan dalam hubungan primer/sekunder, di mana hanya aplikasi utama yang bertanggung jawab atas masalah manajemen utama dan aplikasi sekunder hanya memiliki tampilan baca-saja dari cincin kunci. Aplikasi sekunder dapat dikonfigurasi untuk memperlakukan cincin kunci sebagai baca-saja dengan mengonfigurasi sistem dengan DisableAutomaticKeyGeneration:

builder.Services.AddDataProtection()
    .DisableAutomaticKeyGeneration();

Isolasi per aplikasi

Ketika sistem Perlindungan Data disediakan oleh host ASP.NET Core, sistem tersebut secara otomatis mengisolasi aplikasi satu sama lain, bahkan jika aplikasi tersebut berjalan di bawah akun proses pekerja yang sama dan menggunakan materi kunci master yang sama. Ini mirip dengan pengubah IsolateApps dari elemen System.Web <machineKey> .

Mekanisme isolasi bekerja dengan mempertimbangkan setiap aplikasi pada komputer lokal sebagai penyewa unik, sehingga IDataProtector berakar untuk aplikasi tertentu secara otomatis menyertakan ID aplikasi sebagai diskriminator (ApplicationDiscriminator). ID unik aplikasi adalah jalur fisik aplikasi:

  • Untuk aplikasi yang dihosting di IIS, ID unik adalah jalur fisik IIS aplikasi. Jika aplikasi disebarkan di lingkungan farm web, nilai ini stabil dengan asumsi bahwa lingkungan IIS dikonfigurasi sama di semua komputer di farm web.
  • Untuk aplikasi yang dihost sendiri yang berjalan di Kestrel server, ID unik adalah jalur fisik ke aplikasi di disk.

Pengidentifikasi unik dirancang untuk bertahan dari reset—baik aplikasi individual maupun mesin itu sendiri.

Mekanisme isolasi ini mengasumsikan bahwa aplikasi tidak berbahaya. Aplikasi berbahaya selalu dapat memengaruhi aplikasi lain yang berjalan di bawah akun proses pekerja yang sama. Di lingkungan hosting bersama tempat aplikasi saling tidak tepercaya, penyedia hosting harus mengambil langkah-langkah untuk memastikan isolasi tingkat OS antar aplikasi, termasuk memisahkan repositori kunci yang mendasar aplikasi.

Jika sistem Perlindungan Data tidak disediakan oleh host ASP.NET Core (misalnya, jika Anda membuat instans melalui DataProtectionProvider jenis konkret) isolasi aplikasi dinonaktifkan secara default. Saat isolasi aplikasi dinonaktifkan, semua aplikasi yang didukung oleh materi keying yang sama dapat berbagi payload selama mereka memberikan tujuan yang sesuai. Untuk menyediakan isolasi aplikasi di lingkungan ini, panggil SetApplicationName metode pada objek konfigurasi dan berikan nama unik untuk setiap aplikasi.

Perlindungan Data dan isolasi aplikasi

Pertimbangkan poin berikut untuk isolasi aplikasi:

  • Ketika beberapa aplikasi diarahkan ke repositori kunci yang sama, niatnya adalah bahwa aplikasi berbagi materi kunci master yang sama. Perlindungan Data dikembangkan dengan asumsi bahwa semua aplikasi yang berbagi cincin kunci dapat mengakses semua item di cincin kunci tersebut. Pengidentifikasi unik aplikasi digunakan untuk mengisolasi kunci spesifik aplikasi yang berasal dari kunci yang disediakan cincin kunci. Ini tidak mengharapkan izin tingkat item, seperti yang disediakan oleh Azure KeyVault untuk digunakan untuk memberlakukan isolasi tambahan. Mencoba izin tingkat item menghasilkan kesalahan aplikasi. Jika Anda tidak ingin mengandalkan isolasi aplikasi bawaan, lokasi penyimpanan kunci terpisah harus digunakan dan tidak dibagikan antar aplikasi.

  • Diskriminator aplikasi (ApplicationDiscriminator) digunakan untuk memungkinkan aplikasi yang berbeda berbagi materi kunci master yang sama tetapi untuk menjaga payload kriptografi mereka berbeda satu sama lain. Agar aplikasi dapat membaca payload kriptografi satu sama lain, mereka harus memiliki diskriminator aplikasi yang sama, yang dapat diatur dengan memanggil SetApplicationName.

  • Jika aplikasi disusupi (misalnya, oleh serangan RCE), semua materi kunci master yang dapat diakses oleh aplikasi tersebut juga harus dianggap disusupi, terlepas dari status perlindungan saat istirahat. Ini menyiratkan bahwa jika dua aplikasi ditunjukkan pada repositori yang sama, bahkan jika mereka menggunakan diskriminator aplikasi yang berbeda, kompromi salah satu secara fungsional setara dengan kompromi keduanya.

    Klausul "secara fungsional setara dengan kompromi kedua" ini berlaku meskipun kedua aplikasi menggunakan mekanisme yang berbeda untuk perlindungan kunci saat tidak aktif. Biasanya, ini bukan konfigurasi yang diharapkan. Mekanisme perlindungan saat istirahat dimaksudkan untuk memberikan perlindungan jika lawan mendapatkan akses baca ke repositori. Lawan yang mendapatkan akses tulis ke repositori (mungkin karena mereka mencapai izin eksekusi kode dalam aplikasi) dapat memasukkan kunci berbahaya ke dalam penyimpanan. Sistem Perlindungan Data sengaja tidak memberikan perlindungan terhadap lawan yang mendapatkan akses tulis ke repositori kunci.

  • Jika aplikasi harus tetap benar-benar terisolasi satu dengan yang lain, aplikasi harus menggunakan repositori kunci yang berbeda. Ini secara alami jatuh dari definisi "terisolasi". Aplikasi tidak terisolasi jika semuanya memiliki akses Baca dan Tulis ke penyimpanan data satu sama lain.

Mengubah algoritma dengan UseCryptographicAlgorithms

Tumpukan Perlindungan Data memungkinkan Anda mengubah algoritma default yang digunakan oleh kunci yang baru dibuat. Cara paling sederhana untuk melakukan ini adalah dengan memanggil UseCryptographicAlgorithms dari panggilan balik konfigurasi:

builder.Services.AddDataProtection()
    .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

EncryptionAlgorithm default adalah AES-256-CBC, dan ValidationAlgorithm default adalah HMACSHA256. Kebijakan default dapat ditetapkan oleh administrator sistem melalui kebijakan di seluruh komputer, tetapi panggilan eksplisit untuk UseCryptographicAlgorithms mengambil alih kebijakan default.

Panggilan UseCryptographicAlgorithms memungkinkan Anda menentukan algoritma yang diinginkan dari daftar bawaan yang telah ditentukan sebelumnya. Anda tidak perlu khawatir tentang implementasi algoritma. Dalam skenario di atas, sistem Perlindungan Data mencoba menggunakan implementasi CNG AES jika berjalan di Windows. Jika tidak, itu jatuh kembali ke kelas terkelola System.Security.Cryptography.Aes .

Anda dapat menentukan implementasi secara manual melalui panggilan ke UseCustomCryptographicAlgorithms.

Tip

Mengubah algoritma tidak memengaruhi kunci yang ada di cincin kunci. Ini hanya memengaruhi kunci yang baru dibuat.

Menentukan algoritma terkelola kustom

Untuk menentukan algoritma terkelola kustom, buat ManagedAuthenticatedEncryptorConfiguration instans yang menunjuk ke jenis implementasi:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

Umumnya properti *Jenis harus menunjuk ke implementasi konkret, dapat dibuat (melalui ctor tanpa parameter publik) dari SymmetricAlgorithm dan KeyedHashAlgorithm, meskipun sistem kasus khusus beberapa nilai seperti typeof(Aes) untuk kenyamanan.

Catatan

SymmetricAlgorithm harus memiliki panjang kunci ≥ 128 bit dan ukuran blok ≥ 64 bit, dan harus mendukung enkripsi mode CBC dengan padding PKCS #7. KeyedHashAlgorithm harus memiliki ukuran >hash = 128 bit, dan harus mendukung kunci panjang yang sama dengan panjang hash algoritma hash. KeyedHashAlgorithm tidak benar-benar diperlukan untuk menjadi HMAC.

Menentukan algoritma Windows CNG kustom

Untuk menentukan algoritma Windows CNG kustom menggunakan enkripsi mode CBC dengan validasi HMAC, buat CngCbcAuthenticatedEncryptorConfiguration instans yang berisi informasi algoritma:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Catatan

Algoritma cipher blok simetris harus memiliki panjang >kunci = 128 bit, ukuran >blok = 64 bit, dan harus mendukung enkripsi mode CBC dengan padding PKCS #7. Algoritma hash harus memiliki ukuran >hash = 128 bit dan harus mendukung dibuka dengan bendera BCRYPT_ALG_HANDLE_HMAC_FLAG. Properti *Penyedia dapat diatur ke null untuk menggunakan penyedia default untuk algoritma yang ditentukan. Untuk informasi selengkapnya, lihat dokumentasi BCryptOpenAlgorithmProvider .

Untuk menentukan algoritma Windows CNG kustom menggunakan enkripsi Galois/Mode Penghitung dengan validasi, buat CngGcmAuthenticatedEncryptorConfiguration instans yang berisi informasi algoritma:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Catatan

Algoritma cipher blok simetris harus memiliki panjang >kunci = 128 bit, ukuran blok tepat 128 bit, dan harus mendukung enkripsi GCM. Anda dapat mengatur properti ke EncryptionAlgorithmProvider null untuk menggunakan penyedia default untuk algoritma yang ditentukan. Untuk informasi selengkapnya, lihat dokumentasi BCryptOpenAlgorithmProvider .

Menentukan algoritma kustom lainnya

Meskipun tidak diekspos sebagai API kelas satu, sistem Perlindungan Data cukup dapat diperluas untuk memungkinkan menentukan hampir semua jenis algoritma. Misalnya, dimungkinkan untuk menyimpan semua kunci yang terkandung dalam Modul Keamanan Perangkat Keras (HSM) dan untuk memberikan implementasi kustom dari rutinitas enkripsi dan dekripsi inti. Untuk informasi selengkapnya, lihat IAuthenticatedEncryptor di Ekstensibilitas kriptografi inti.

Mempertahankan kunci saat menghosting dalam kontainer Docker

Saat menghosting dalam kontainer Docker , kunci harus dipertahankan di:

Kunci persisten dengan Redis

Hanya versi Redis yang mendukung Redis Data Persistence yang harus digunakan untuk menyimpan kunci. Penyimpanan Azure Blob persisten dan dapat digunakan untuk menyimpan kunci. Untuk informasi lebih lanjut, lihat masalah GitHub ini.

Pengelogan DataProtection

Aktifkan Information pengelogan tingkat DataProtection untuk membantu masalah diagnosis. File berikut appsettings.json memungkinkan pengelogan informasi API DataProtection:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  },
  "AllowedHosts": "*"
}

Untuk informasi selengkapnya tentang pengelogan, lihat Pengelogan di .NET Core dan ASP.NET Core.

Sumber Daya Tambahan:

Ketika sistem Perlindungan Data diinisialisasi, sistem menerapkan pengaturan default berdasarkan lingkungan operasional. Pengaturan ini sesuai untuk aplikasi yang berjalan pada satu komputer. Namun, ada kasus di mana pengembang mungkin ingin mengubah pengaturan default:

  • Aplikasi ini tersebar di beberapa komputer.
  • Untuk alasan kepatuhan.

Untuk skenario ini, sistem Perlindungan Data menawarkan API konfigurasi yang kaya.

Peringatan

Mirip dengan file konfigurasi, cincin kunci perlindungan data harus dilindungi menggunakan izin yang sesuai. Anda dapat memilih untuk mengenkripsi kunci saat tidak aktif, tetapi ini tidak mencegah penyerang membuat kunci baru. Akibatnya, keamanan aplikasi Anda terpengaruh. Lokasi penyimpanan yang dikonfigurasi dengan Perlindungan Data harus memiliki akses terbatas pada aplikasi itu sendiri, mirip dengan cara Anda akan melindungi file konfigurasi. Misalnya, jika Anda memilih untuk menyimpan cincin kunci di disk, gunakan izin sistem file. Pastikan hanya identitas tempat aplikasi web Anda berjalan telah membaca, menulis, dan membuat akses ke direktori tersebut. Jika Anda menggunakan Azure Blob Storage, hanya aplikasi web yang harus memiliki kemampuan untuk membaca, menulis, atau membuat entri baru di penyimpanan blob, dll.

Metode AddDataProtection ekstensi mengembalikan IDataProtectionBuilder. IDataProtectionBuilder mengekspos metode ekstensi yang dapat Anda rantai bersama-sama untuk mengonfigurasi opsi Perlindungan Data.

Paket NuGet berikut diperlukan untuk ekstensi Perlindungan Data yang digunakan dalam artikel ini:

ProtectKeysWithAzureKeyVault

Masuk ke Azure menggunakan CLI, misalnya:

az login

Untuk menyimpan kunci di Azure Key Vault, konfigurasikan sistem dengan ProtectKeysWithAzureKeyVault di Startup kelas . blobUriWithSasToken adalah URI lengkap tempat file kunci harus disimpan. URI harus berisi token SAS sebagai parameter string kueri:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
        .ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());
}

Agar aplikasi dapat berkomunikasi dan mengotorisasi dirinya sendiri dengan KeyVault, paket Azure.Identity harus ditambahkan.

Atur lokasi penyimpanan cincin kunci (misalnya, PersistKeysToAzureBlobStorage). Lokasi harus diatur karena panggilan ProtectKeysWithAzureKeyVault mengimplementasikan IXmlEncryptor yang menonaktifkan pengaturan perlindungan data otomatis, termasuk lokasi penyimpanan cincin kunci. Contoh sebelumnya menggunakan Azure Blob Storage untuk mempertahankan cincin kunci. Untuk informasi selengkapnya, lihat Penyedia penyimpanan utama: Azure Storage. Anda juga dapat mempertahankan cincin kunci secara lokal dengan PersistKeysToFileSystem.

keyIdentifier adalah pengidentifikasi kunci brankas kunci yang digunakan untuk enkripsi kunci. Misalnya, kunci yang dibuat di brankas kunci bernama dataprotection di contosokeyvault memiliki pengidentifikasi https://contosokeyvault.vault.azure.net/keys/dataprotection/kunci . Berikan izin Get, Unwrap Key, dan Wrap Key ke brankas kunci.

ProtectKeysWithAzureKeyVault kelebihan beban:

Jika aplikasi menggunakan paket Azure yang lebih lama (Microsoft.AspNetCore.DataProtection.AzureStorage dan Microsoft.AspNetCore.DataProtection.AzureKeyVault), sebaiknya hapus referensi ini dan tingkatkan ke Azure.Extensions.AspNetCore.DataProtection.Blobs dan Azure.Extensions.AspNetCore.DataProtection.Keys. Paket-paket ini adalah tempat pembaruan baru disediakan, dan mengatasi beberapa masalah keamanan dan stabilitas utama dengan paket yang lebih lama.

services.AddDataProtection()
    //This blob must already exist before the application is run
    .PersistKeysToAzureBlobStorage("<storage account connection string", "<key store container name>", "<key store blob name>")
    //Removing this line below for an initial run will ensure the file is created correctly
    .ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());

PersistKeysToFileSystem

Untuk menyimpan kunci pada berbagi UNC, bukan di lokasi default %LOCALAPPDATA% , konfigurasikan sistem dengan PersistKeysToFileSystem:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}

Peringatan

Jika Anda mengubah lokasi persistensi kunci, sistem tidak lagi secara otomatis mengenkripsi kunci saat tidak aktif, karena tidak tahu apakah DPAPI adalah mekanisme enkripsi yang sesuai.

PersistKeysToDbContext

Untuk menyimpan kunci dalam database menggunakan EntityFramework, konfigurasikan sistem dengan paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToDbContext<DbContext>()
}

Kode sebelumnya menyimpan kunci dalam database yang dikonfigurasi. Konteks database yang digunakan harus menerapkan IDataProtectionKeyContext. IDataProtectionKeyContext mengekspos properti DataProtectionKeys

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }

Properti ini mewakili tabel tempat kunci disimpan. Buat tabel secara manual atau dengan DbContext Migrasi. Untuk informasi selengkapnya, lihat DataProtectionKey .

ProtectKeysWith*

Anda dapat mengonfigurasi sistem untuk melindungi kunci saat tidak aktif dengan memanggil salah satu API konfigurasi ProtectKeysWith* . Pertimbangkan contoh di bawah ini, yang menyimpan kunci pada berbagi UNC dan mengenkripsi kunci tersebut saat tidak aktif dengan sertifikat X.509 tertentu:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}

Anda dapat menyediakan X509Certificate2 ke ProtectKeysWithCertificate, seperti sertifikat yang dimuat dari file:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}

Lihat Enkripsi Kunci Saat Istirahat untuk contoh dan diskusi selengkapnya tentang mekanisme enkripsi kunci bawaan.

UnprotectKeysWithAnyCertificate

Anda dapat memutar sertifikat dan mendekripsi kunci saat tidak aktif menggunakan array X509Certificate2 sertifikat dengan UnprotectKeysWithAnyCertificate:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
        .UnprotectKeysWithAnyCertificate(
            new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
            new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}

SetDefaultKeyLifetime

Untuk mengonfigurasi sistem untuk menggunakan masa pakai kunci 14 hari alih-alih default 90 hari, gunakan SetDefaultKeyLifetime:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}

SetApplicationName

Secara default, sistem Perlindungan Data mengisolasi aplikasi satu sama lain berdasarkan jalur akar kontennya, bahkan jika mereka berbagi repositori kunci fisik yang sama. Isolasi ini mencegah aplikasi memahami payload yang dilindungi satu sama lain.

Untuk berbagi payload yang dilindungi di antara aplikasi:

  • Konfigurasikan SetApplicationName di setiap aplikasi dengan nilai yang sama.
  • Gunakan versi tumpukan API Perlindungan Data yang sama di seluruh aplikasi. Lakukan salah satu hal berikut dalam file proyek aplikasi:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetApplicationName("shared app name");
}

SetApplicationName secara internal menetapkan DataProtectionOptions.ApplicationDiscriminator. Untuk informasi selengkapnya tentang bagaimana diskriminator digunakan, lihat bagian berikut ini nanti di artikel ini:

DisableAutomaticKeyGeneration

Anda mungkin memiliki skenario di mana Anda tidak ingin aplikasi secara otomatis menggulung kunci (membuat kunci baru) saat mendekati kedaluwarsa. Salah satu contoh skenario ini mungkin adalah aplikasi yang disiapkan dalam hubungan primer/sekunder, di mana hanya aplikasi utama yang bertanggung jawab atas masalah manajemen utama dan aplikasi sekunder hanya memiliki tampilan baca-saja dari cincin kunci. Aplikasi sekunder dapat dikonfigurasi untuk memperlakukan cincin kunci sebagai baca-saja dengan mengonfigurasi sistem dengan DisableAutomaticKeyGeneration:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .DisableAutomaticKeyGeneration();
}

Isolasi per aplikasi

Ketika sistem Perlindungan Data disediakan oleh host ASP.NET Core, sistem tersebut secara otomatis mengisolasi aplikasi satu sama lain, bahkan jika aplikasi tersebut berjalan di bawah akun proses pekerja yang sama dan menggunakan materi kunci master yang sama. Ini mirip dengan pengubah IsolateApps dari elemen System.Web <machineKey> .

Mekanisme isolasi bekerja dengan mempertimbangkan setiap aplikasi pada komputer lokal sebagai penyewa unik, sehingga IDataProtector berakar untuk aplikasi tertentu secara otomatis menyertakan ID aplikasi sebagai diskriminator (ApplicationDiscriminator). ID unik aplikasi adalah jalur fisik aplikasi:

  • Untuk aplikasi yang dihosting di IIS, ID unik adalah jalur fisik IIS aplikasi. Jika aplikasi disebarkan di lingkungan farm web, nilai ini stabil dengan asumsi bahwa lingkungan IIS dikonfigurasi sama di semua komputer di farm web.
  • Untuk aplikasi yang dihost sendiri yang berjalan di Kestrel server, ID unik adalah jalur fisik ke aplikasi di disk.

Pengidentifikasi unik dirancang untuk bertahan dari reset—baik aplikasi individual maupun mesin itu sendiri.

Mekanisme isolasi ini mengasumsikan bahwa aplikasi tidak berbahaya. Aplikasi berbahaya selalu dapat memengaruhi aplikasi lain yang berjalan di bawah akun proses pekerja yang sama. Di lingkungan hosting bersama tempat aplikasi saling tidak tepercaya, penyedia hosting harus mengambil langkah-langkah untuk memastikan isolasi tingkat OS antar aplikasi, termasuk memisahkan repositori kunci yang mendasar aplikasi.

Jika sistem Perlindungan Data tidak disediakan oleh host ASP.NET Core (misalnya, jika Anda membuat instans melalui DataProtectionProvider jenis konkret) isolasi aplikasi dinonaktifkan secara default. Saat isolasi aplikasi dinonaktifkan, semua aplikasi yang didukung oleh materi keying yang sama dapat berbagi payload selama mereka memberikan tujuan yang sesuai. Untuk menyediakan isolasi aplikasi di lingkungan ini, panggil metode SetApplicationName pada objek konfigurasi dan berikan nama unik untuk setiap aplikasi.

Perlindungan Data dan isolasi aplikasi

Pertimbangkan poin berikut untuk isolasi aplikasi:

  • Ketika beberapa aplikasi diarahkan ke repositori kunci yang sama, niatnya adalah bahwa aplikasi berbagi materi kunci master yang sama. Perlindungan Data dikembangkan dengan asumsi bahwa semua aplikasi yang berbagi cincin kunci dapat mengakses semua item di cincin kunci tersebut. Pengidentifikasi unik aplikasi digunakan untuk mengisolasi kunci spesifik aplikasi yang berasal dari kunci yang disediakan cincin kunci. Ini tidak mengharapkan izin tingkat item, seperti yang disediakan oleh Azure KeyVault untuk digunakan untuk memberlakukan isolasi tambahan. Mencoba izin tingkat item menghasilkan kesalahan aplikasi. Jika Anda tidak ingin mengandalkan isolasi aplikasi bawaan, lokasi penyimpanan kunci terpisah harus digunakan dan tidak dibagikan antar aplikasi.

  • Diskriminator aplikasi (ApplicationDiscriminator) digunakan untuk memungkinkan aplikasi yang berbeda berbagi materi kunci master yang sama tetapi untuk menjaga payload kriptografi mereka berbeda satu sama lain. Agar aplikasi dapat membaca payload kriptografi satu sama lain, mereka harus memiliki diskriminator aplikasi yang sama, yang dapat diatur dengan memanggil SetApplicationName.

  • Jika aplikasi disusupi (misalnya, oleh serangan RCE), semua materi kunci master yang dapat diakses oleh aplikasi tersebut juga harus dianggap disusupi, terlepas dari status perlindungan saat istirahat. Ini menyiratkan bahwa jika dua aplikasi ditunjukkan pada repositori yang sama, bahkan jika mereka menggunakan diskriminator aplikasi yang berbeda, kompromi salah satu secara fungsional setara dengan kompromi keduanya.

    Klausul "secara fungsional setara dengan kompromi kedua" ini berlaku meskipun kedua aplikasi menggunakan mekanisme yang berbeda untuk perlindungan kunci saat tidak aktif. Biasanya, ini bukan konfigurasi yang diharapkan. Mekanisme perlindungan saat istirahat dimaksudkan untuk memberikan perlindungan jika lawan mendapatkan akses baca ke repositori. Lawan yang mendapatkan akses tulis ke repositori (mungkin karena mereka mencapai izin eksekusi kode dalam aplikasi) dapat memasukkan kunci berbahaya ke dalam penyimpanan. Sistem Perlindungan Data sengaja tidak memberikan perlindungan terhadap lawan yang mendapatkan akses tulis ke repositori kunci.

  • Jika aplikasi harus tetap benar-benar terisolasi satu dengan yang lain, aplikasi harus menggunakan repositori kunci yang berbeda. Ini secara alami jatuh dari definisi "terisolasi". Aplikasi tidak terisolasi jika semuanya memiliki akses Baca dan Tulis ke penyimpanan data satu sama lain.

Mengubah algoritma dengan UseCryptographicAlgorithms

Tumpukan Perlindungan Data memungkinkan Anda mengubah algoritma default yang digunakan oleh kunci yang baru dibuat. Cara paling sederhana untuk melakukan ini adalah dengan memanggil UseCryptographicAlgorithms dari panggilan balik konfigurasi:

services.AddDataProtection()
    .UseCryptographicAlgorithms(
        new AuthenticatedEncryptorConfiguration()
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

EncryptionAlgorithm default adalah AES-256-CBC, dan ValidationAlgorithm default adalah HMACSHA256. Kebijakan default dapat ditetapkan oleh administrator sistem melalui kebijakan di seluruh komputer, tetapi panggilan eksplisit untuk UseCryptographicAlgorithms mengambil alih kebijakan default.

Panggilan UseCryptographicAlgorithms memungkinkan Anda menentukan algoritma yang diinginkan dari daftar bawaan yang telah ditentukan sebelumnya. Anda tidak perlu khawatir tentang implementasi algoritma. Dalam skenario di atas, sistem Perlindungan Data mencoba menggunakan implementasi CNG AES jika berjalan di Windows. Jika tidak, itu jatuh kembali ke kelas terkelola System.Security.Cryptography.Aes .

Anda dapat menentukan implementasi secara manual melalui panggilan ke UseCustomCryptographicAlgorithms.

Tip

Mengubah algoritma tidak memengaruhi kunci yang ada di cincin kunci. Ini hanya memengaruhi kunci yang baru dibuat.

Menentukan algoritma terkelola kustom

Untuk menentukan algoritma terkelola kustom, buat ManagedAuthenticatedEncryptorConfiguration instans yang menunjuk ke jenis implementasi:

serviceCollection.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new ManagedAuthenticatedEncryptorConfiguration()
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

Umumnya properti *Jenis harus menunjuk ke implementasi konkret, dapat dibuat (melalui ctor tanpa parameter publik) dari SymmetricAlgorithm dan KeyedHashAlgorithm, meskipun sistem kasus khusus beberapa nilai seperti typeof(Aes) untuk kenyamanan.

Catatan

SymmetricAlgorithm harus memiliki panjang kunci ≥ 128 bit dan ukuran blok ≥ 64 bit, dan harus mendukung enkripsi mode CBC dengan padding PKCS #7. KeyedHashAlgorithm harus memiliki ukuran >hash = 128 bit, dan harus mendukung kunci panjang yang sama dengan panjang hash algoritma hash. KeyedHashAlgorithm tidak benar-benar diperlukan untuk menjadi HMAC.

Menentukan algoritma Windows CNG kustom

Untuk menentukan algoritma Windows CNG kustom menggunakan enkripsi mode CBC dengan validasi HMAC, buat CngCbcAuthenticatedEncryptorConfiguration instans yang berisi informasi algoritma:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngCbcAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Catatan

Algoritma cipher blok simetris harus memiliki panjang >kunci = 128 bit, ukuran >blok = 64 bit, dan harus mendukung enkripsi mode CBC dengan padding PKCS #7. Algoritma hash harus memiliki ukuran >hash = 128 bit dan harus mendukung dibuka dengan bendera BCRYPT_ALG_HANDLE_HMAC_FLAG. Properti *Penyedia dapat diatur ke null untuk menggunakan penyedia default untuk algoritma yang ditentukan. Untuk informasi selengkapnya, lihat dokumentasi BCryptOpenAlgorithmProvider .

Untuk menentukan algoritma Windows CNG kustom menggunakan enkripsi Galois/Mode Penghitung dengan validasi, buat CngGcmAuthenticatedEncryptorConfiguration instans yang berisi informasi algoritma:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngGcmAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Catatan

Algoritma cipher blok simetris harus memiliki panjang >kunci = 128 bit, ukuran blok tepat 128 bit, dan harus mendukung enkripsi GCM. Anda dapat mengatur properti ke EncryptionAlgorithmProvider null untuk menggunakan penyedia default untuk algoritma yang ditentukan. Untuk informasi selengkapnya, lihat dokumentasi BCryptOpenAlgorithmProvider .

Menentukan algoritma kustom lainnya

Meskipun tidak diekspos sebagai API kelas satu, sistem Perlindungan Data cukup dapat diperluas untuk memungkinkan menentukan hampir semua jenis algoritma. Misalnya, dimungkinkan untuk menyimpan semua kunci yang terkandung dalam Modul Keamanan Perangkat Keras (HSM) dan untuk memberikan implementasi kustom dari rutinitas enkripsi dan dekripsi inti. Untuk informasi selengkapnya, lihat IAuthenticatedEncryptor di Ekstensibilitas kriptografi inti.

Mempertahankan kunci saat menghosting dalam kontainer Docker

Saat menghosting dalam kontainer Docker , kunci harus dipertahankan di:

Kunci persisten dengan Redis

Hanya versi Redis yang mendukung Redis Data Persistence yang harus digunakan untuk menyimpan kunci. Penyimpanan Azure Blob persisten dan dapat digunakan untuk menyimpan kunci. Untuk informasi lebih lanjut, lihat masalah GitHub ini.

Pengelogan DataProtection

Aktifkan Information pengelogan tingkat DataProtection untuk membantu masalah diagnosis. File berikut appsettings.json memungkinkan pengelogan informasi API DataProtection:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  }
}

Untuk informasi selengkapnya tentang pengelogan, lihat Pengelogan di .NET Core dan ASP.NET Core.

Sumber Daya Tambahan: