Web Crypto API: Dosya Şifreleme İçin Eksiksiz Eğitim
Browser tabanlı dosya şifreleme için Web Crypto API'ye hakim olun. JavaScript uygulamalarında AES-GCM, RSA-OAEP ve anahtar yönetimi.
Web Crypto API, harici kütüphane gerektirmeksizin window.crypto.subtle yöntemleriyle doğrudan tarayıcıda dosya şifrelemenize olanak tanır. Dosya şifreleme için tipik akış: PBKDF2 ile paroladan anahtar türetme (210.000 iterasyon, SHA-256), ardından 96 bitlik IV ve 128 bitlik kimlik doğrulama etiketiyle AES-GCM kullanarak dosya baytlarını şifreleme. Açık anahtar iş akışları, simetrik anahtarı sarmak için 4096 bitlik anahtarlarla RSA-OAEP kullanır. API, her modern tarayıcıda HTTPS üzerinden erişilebilir ve JavaScript yerine tarayıcının yerel kripto arka ucunda çalışır.
SubtleCrypto'nun Saf-JS Kütüphanelerden Üstünlüğü
window.crypto.subtle, Chromium'da genellikle BoringSSL, Safari'de CommonCrypto olan tarayıcının denetlenmiş yerel kripto arka ucuna çağrı yapar. CryptoJS veya sjcl gibi saf-JS seçeneklerle karşılaştırıldığında SubtleCrypto, AES-GCM için 30-80 kat daha hızlı çalışır, JavaScript yorumlayıcılarındaki zamanlama yan kanallarından kaçınır ve kullanıcılara sıfır bayt gönderir. Dezavantajı yalnızca ArrayBuffer ve CryptoKey nesneleri üzerinde çalışan Promise tabanlı bir API'dir; dolayısıyla Uint8Array, Blob ve ReadableStream arasında sürekli dönüştürme yaparsınız. 100 MB'ın üzerindeki dosya boyutları için bu altyapı, ham kripto hızından daha önemli hale gelir.
PBKDF2 ile Paroladan Anahtar Türetme
Parolayı doğrudan AES anahtarı olarak asla kullanmayın. Bunun yerine parolayı ham malzeme olarak içe aktarın, ardından 256 bitlik anahtar türetin:
async function deriveKey(password, salt) {
const enc = new TextEncoder();
const material = await crypto.subtle.importKey(
'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']
);
return crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 210000, hash: 'SHA-256' },
material,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
}
OWASP'ın 2026 rehberi SHA-256 ile en az 600.000 iterasyon önerir; 210.000 ise düşük riskli bağlamlar için hâlâ kabul edilebilir. Her dosya için crypto.getRandomValues ile 16 baytlık yeni tuz üretin ve şifreli metnin yanında saklayın. Argon2id daha güçlü olurdu ancak SubtleCrypto henüz onu göstermiyor.
AES-GCM ile Dosya Şifreleme
AES-GCM tek geçişte gizlilik ve kimlik doğrululuğu sağlar. Kritik kural (anahtar, IV) çiftini asla yeniden kullanmamaktır:
async function encryptFile(file, key) {
const iv = crypto.getRandomValues(new Uint8Array(12));
const plaintext = await file.arrayBuffer();
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv, tagLength: 128 },
key,
plaintext
);
return { iv, ciphertext };
}
2 GB'lık dosya için file.arrayBuffer() tüm tamponu tahsis eder; bu durum genellikle mobil Safari'yi çökertir. Dosyayı 4 MB'lık parçalara bölün, her birini rastgele bir ön eke bitiştirilmiş sayaçtan türetilen benzersiz IV ile şifreleyin ve şifre çözücünün neyle karşı karşıya olduğunu bilmesi için bir sürüm baytı ve tuz hazırlayın.
Büyük Dosyaları TransformStream ile Akıtma
Bellek patlamasını önlemek için şifrelemeyi TransformStream içine sarın ve dosyayı bunun üzerinden aktarın:
const chunkSize = 4 * 1024 * 1024;
const encryptor = new TransformStream({
async transform(chunk, controller) {
const iv = nextIV(counter++);
const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, chunk);
controller.enqueue(new Uint8Array([...iv, ...new Uint8Array(ct)]));
}
});
await file.stream()
.pipeThrough(sliceByChunks(chunkSize))
.pipeThrough(encryptor)
.pipeTo(uploadSink);
file.stream(), diskten tembel okuma yapan ReadableStream<Uint8Array> döndürür. Dilimleyici, GCM etiketlerinin tahmin edilebilir biçimde hizalanması için sabit boyutlu parçalar üretir. Zirve bellek kullanımı 10 GB'lık yüklemede bile 20 MB'ın altında kalır.
RSA-OAEP ile Simetrik Anahtarı Sarma
Dosyayı belirli bir alıcıyla paylaşmanız gerektiğinde, alıcının RSA anahtar çiftini bir kez oluşturun ve açık anahtarı yayınlayın:
const keypair = await crypto.subtle.generateKey(
{ name: 'RSA-OAEP', modulusLength: 4096,
publicExponent: new Uint8Array([1,0,1]), hash: 'SHA-256' },
true, ['wrapKey', 'unwrapKey']
);
Dosya için bir AES-GCM anahtarı oluşturun, ardından sarın:
const wrapped = await crypto.subtle.wrapKey(
'raw', fileKey, keypair.publicKey,
{ name: 'RSA-OAEP' }
);
4096 bitlik RSA anahtarları NIST SP 800-57'ye göre 2030'a kadar yaklaşık 150 bitlik güvenlik sağlar. İleri gizlilik veya kuantum sonrası direnç gerekiyorsa RSA-OAEP'i P-384 üzerinde ECDH ile eşleştirin veya WebCrypto çalışma grubu ML-KEM'i (Kyber) implemente ettiğinde buna geçin.
IndexedDB'de Anahtarları Güvenli Saklama
CryptoKey nesneleri varsayılan olarak çıkarılamaz niteliktedir; bu, raw baytları JavaScript'e açmadan IndexedDB'de kalıcı hale getirebileceğiniz anlamına gelir:
const db = await openDB('keystore', 1);
await db.put('keys', keypair.privateKey, 'user-signing-key');
Tarayıcılar anahtarı yapılandırılmış klon algoritmasıyla serileştirir ve gerçek baytları kripto arka ucunda tutar. Ele geçirilmiş bir script saklanan anahtarla encrypt veya decrypt çağırabilir, ancak materyali okuyamaz. Bu, base64 anahtarları localStorage'a koymaya göre anlamlı bir sertleştirme adımıdır.
API'nin Fırlattığı Hatalar
SubtleCrypto, kimlik doğrulamalı şifre çözme hatalarında OperationError fırlatır — bu genellikle şifreli metnin kurcalandığı, IV'nin yanlış olduğu veya kullanıcının yanlış parola girdiği anlamına gelir. Giriş tamponunun yanlış uzunlukta olduğunda DataError, algoritmanın uygulanmadığında NotSupportedError, anahtarın doğru kullanım bayraklarıyla içe aktarılmadığında InvalidAccessError fırlatır. Şifre çözmeyi her zaman try/catch içine alın, tarafsız bir "dosya çözülemedi" mesajı gösterin ve etiketin mi yoksa yapının mı başarısız olduğunu sızdırmaktan kaçının.
Gerçek Dünya Tuzakları
Android'de Firefox, deriveKey iterasyonlarını arayüz iş parçacığı birkaç saniye donmadan önce yaklaşık 1 milyonla sınırlar; bu nedenle anahtar türetmeyi özel bir Worker içinde çalıştırın. 16.4'ün altındaki Safari, PSS dolgusuyla crypto.subtle.verify'yi desteklemez. Chrome, çağrı başına 64 KB'ın üzerindeki getRandomValues çağrılarını kısıtlar; daha fazla entropi gerekiyorsa döngüye alın. postMessage aracılığıyla ArrayBuffer aktarımları sıfır kopyalıdır ancak orijinali ayırır — bu insanları şaşırtır.
HexaTransfer, her yükleme için tam olarak bu AES-GCM artı PBKDF2 boru hattını kullanır; anahtarlar Worker'da türetilir ve şifreli metin sunucunun hiç düz metin görmemesi şekliyle depolamaya aktarılır. hexatransfer.com'da deneyin — ücretsiz, hesap gerekmez, maksimum 10 GB.
Hepsini Bir Araya Getirme
Minimum şifreli yükleme akışı: getRandomValues ile tuz ve IV üretin, PBKDF2 aracılığıyla kullanıcının parolasından AES-GCM anahtarı türetin, her 4 MB'lık parçayı şifreleyen bir TransformStream üzerinden dosyayı aktarın, sürüm, tuz ve parça sayısını içeren küçük bir başlık hazırlayın ve sonucu sunucunuza POST isteğiyle gönderin. İndirmede, yanlış parola veya bozulma sinyali olarak OperationError'ı yakalayarak işlemi parça parça tersine çevirin. Web Crypto API ihtiyacınız olan her şeyi sağlar ve tarayıcının yerel uygulaması herhangi bir JavaScript alternatifini büyük farkla geride bırakır.
Uçtan uca şifreleme ile büyük dosyaları güvenle gönderin
Uçtan uca şifreleme ile 10 GB'a kadar dosya ücretsiz aktarın. Hesap gerekmez. Dosyalarınız yüklenmeden önce tarayıcınızda şifrelenir — başka kimse okuyamaz.
Dosya gönder