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 di rest, tetapi ini tidak mencegah serangan cyber 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 tempat aplikasi web Anda berjalan telah membaca, menulis, dan membuat akses ke direktori tersebut identity . 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.
Catatan
Artikel ini ditulis untuk aplikasi yang berjalan dalam kontainer docker. Dalam kontainer docker, aplikasi selalu memiliki jalur yang sama dan, oleh karena itu, diskriminator aplikasi yang sama. Aplikasi yang perlu berjalan di beberapa lingkungan (misalnya lokal dan disebarkan), harus mengatur diskriminator aplikasi default untuk lingkungan. Menjalankan aplikasi di beberapa lingkungan berada di luar cakupan artikel ini.
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:
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, Uri, TokenCredential) mengizinkan penggunaan keyIdentifier Uri dan tokenCredential untuk memungkinkan sistem perlindungan data menggunakan brankas kunci.
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, IKeyEncryptionKeyResolver) mengizinkan penggunaan string keyIdentifier dan IKeyEncryptionKeyResolver untuk memungkinkan sistem perlindungan data menggunakan brankas kunci.
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 di rest, 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 dengan rest memanggil salah satu API konfigurasi ProtectKeysWith* . Pertimbangkan contoh di bawah ini, yang menyimpan kunci pada berbagi UNC dan mengenkripsi kunci tersebut di rest 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 Di Rest untuk contoh dan diskusi selengkapnya tentang mekanisme enkripsi kunci bawaan.
UnprotectKeysWithAnyCertificate
Anda dapat memutar sertifikat dan mendekripsi kunci menggunakan rest 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:
- Referensikan versi kerangka kerja bersama yang sama melalui metapackage Microsoft.AspNetCore.App.
- Referensikan versi paket Perlindungan Data yang sama.
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 perlindungannyarest . 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 di rest. Biasanya, ini bukan konfigurasi yang diharapkan. Mekanisme perlindungan-di-dimaksudkanrest untuk memberikan perlindungan jika cyberattacker mendapatkan akses baca ke repositori. Penyerang cyber 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 penyerang cyber 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:
- Folder yang merupakan volume Docker yang bertahan di luar masa pakai kontainer, seperti volume bersama atau volume yang dipasang host.
- Penyedia eksternal, seperti Azure Blob Storage (diperlihatkan di bagian
ProtectKeysWithAzureKeyVault
) atau Redis.
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 di rest, tetapi ini tidak mencegah serangan cyber 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 tempat aplikasi web Anda berjalan telah membaca, menulis, dan membuat akses ke direktori tersebut identity . 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:
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, Uri, TokenCredential) mengizinkan penggunaan keyIdentifier Uri dan tokenCredential untuk memungkinkan sistem perlindungan data menggunakan brankas kunci.
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, IKeyEncryptionKeyResolver) mengizinkan penggunaan string keyIdentifier dan IKeyEncryptionKeyResolver untuk memungkinkan sistem perlindungan data menggunakan brankas kunci.
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 di rest, 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 dengan rest memanggil salah satu API konfigurasi ProtectKeysWith* . Pertimbangkan contoh di bawah ini, yang menyimpan kunci pada berbagi UNC dan mengenkripsi kunci tersebut di rest 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 Di Rest untuk contoh dan diskusi selengkapnya tentang mekanisme enkripsi kunci bawaan.
UnprotectKeysWithAnyCertificate
Anda dapat memutar sertifikat dan mendekripsi kunci menggunakan rest 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:
- Referensikan versi kerangka kerja bersama yang sama melalui metapackage Microsoft.AspNetCore.App.
- Referensikan versi paket Perlindungan Data yang sama.
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 perlindungannyarest . 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 di rest. Biasanya, ini bukan konfigurasi yang diharapkan. Mekanisme perlindungan-di-dimaksudkanrest untuk memberikan perlindungan jika cyberattacker mendapatkan akses baca ke repositori. Penyerang cyber 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 penyerang cyber 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:
- Folder yang merupakan volume Docker yang bertahan di luar masa pakai kontainer, seperti volume bersama atau volume yang dipasang host.
- Penyedia eksternal, seperti Azure Blob Storage (diperlihatkan di bagian
ProtectKeysWithAzureKeyVault
) atau Redis.
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:
ASP.NET Core