İçeriğe geç

Delilleri Çevrimdışı Doğrulama

Delil paketi, panelden dışa aktarılan bir ZIP dosyasıdır. Onay kayıtlarını, bunları kontrol etmek için gereken dosyaları ve kontrolleri çalıştıran scriptleri içerir. Bu sayfadaki hiçbir şey ağ bağlantısı veya bir HashEntry sunucusu gerektirmez.

Bu sayfa, her kontrolün neyi ortaya koyduğunu belirtir. Tek başına hiçbir kontrol bir kaydı “değiştirilemez” kılmaz; kontroller birlikte, üçüncü bir tarafın değişiklikleri tespit etmesine ve bir kaydı belirli bir zaman noktasına bağlamasına olanak tanır.


Dosyaİçerik
consent_data.jsonDışa aktarılan kayıtlar. Her kayıtta, hash’lenen payload’ı içeren bir proof bloğu bulunur.
manifest.json, metadata.jsonPaket kimliği, spesifikasyon sürümü, kayıt sayısı, package_hash.
checksums.sha256Paketteki her dosyanın SHA-256 değeri.
timestamps.tsv + *.tsrRFC 3161 zaman damgası token’ları (tsa_consent_<id>.tsr, tsa_epoch_<id>.tsr, package.tsr) ve her birinin neyi kapsadığı.
merkle_proofs.tsvMerkle dahil edilme kanıtları (gruplar hâlinde zaman damgası vurulan kayıtlar için).
verify.sh, verify.ps1, README_*.txt, proof_verification.txtDoğrulama scriptleri ve talimatlar.

Paketler iki türdür: imzasız (yalnızca sağlama toplamları) ve imzalı (paket hash’i ayrıca bir RFC 3161 zaman damgası taşır: package.tsr).

Terminal window
# Linux / macOS
chmod +x verify.sh && ./verify.sh
Terminal window
# Windows
powershell -ExecutionPolicy Bypass -File .\verify.ps1

Scriptler dosya sağlama toplamlarını, manifest’i, zaman damgalarını ve Merkle kanıtlarını kontrol eder. Kanıt hash’ini yeniden hesaplamazlar; çünkü bunun için veri sorumlusunun gizli anahtarı gerekir (aşağıya bakın).


Terminal window
sha256sum -c checksums.sha256 # macOS: shasum -a 256 -c checksums.sha256
sha256sum consent_data.json # manifest.json içindeki "package_hash" değerine eşit olmalıdır

Bu, dosyaların pakette listelenen dosyalar olduğunu gösterir. Tek başına, paketi kimin veya ne zaman oluşturduğunu göstermez — bir dosyayı değiştirdikten sonra sağlama toplamlarını herkes yeniden hesaplayabilir. İmzalı bir paketteki zaman damgası bunun içindir.

Her kaydın bir proof_hash değeri vardır. Güncel kayıtlar için (hash_version: 2):

proof_hash = HMAC-SHA256( key = tenant secret key, message = canonical_json(payload) ) → lowercase hex

Payload her zaman şu on bir anahtara sahiptir (eksik bir değer null olur):

v (= 2), site_id, document_hash, consent_type, decision, categories, timestamp,
pii_digest, signer_digest, custom_document_hash, signature_hash
  • timestamp, saniye hassasiyetinde UTC’dir, YYYY-MM-DDTHH:MM:SS+00:00 biçimindedir ve kaydın oluşturulma zamanına eşittir.
  • Kişisel veriler hash’e doğrudan girmez. Tuzlanmış (salted) özetler aracılığıyla girer: pii_digest = SHA-256( pii_salt || canonical_json({ip_address, user_agent, visitor_id}) ) ve signer_digest = SHA-256( pii_salt || canonical_json(signer evidence fields) ) (imza veya kimlik beyanı yoksa null). Bir kayıt anonimleştirildiğinde kişisel alanlar ve tuz silinir, ancak özetler kalır; böylece kanıt hash’i yine yeniden hesaplanabilirken özetler artık bir IP veya e-posta adresiyle ilişkilendirilemez.

Kanonik JSON (HashEntry Canonical JSON v2 — bu, RFC 8785 değildir):

  1. UTF-8, token’lar arasında boşluk yok.
  2. Nesne anahtarları, her düzeyde UTF-8 bayt sırasına göre sıralanır.
  3. Dizi sırası korunur.
  4. Boş bir nesne de boş bir dizi de [] olarak yazılır.
  5. Dizelerde yalnızca ", \ ve U+0000–U+001F kontrol karakterleri kaçışlanır; / ve ASCII olmayan karakterler kaçışlanmaz.
  6. Sayılar yalnızca tam sayıdır.
  7. true, false, null küçük harfle yazılır.

Kim kontrol edebilir. Kanıt hash’i anahtarlı bir hash’tir. Yeniden hesaplanması tenant’ın gizli anahtarını gerektirir; dolayısıyla (anahtarı elinde tutan) veri sorumlusu veya veri sorumlusunun anahtarı verdiği bir bilirkişi tarafından kontrol edilebilir. Anahtar olmadan üçüncü bir taraf onu yeniden hesaplayamaz — buna ihtiyacı da yoktur: aşağıdaki zaman damgası ve Merkle kontrolleri proof_hash değerinin kendisi üzerinde çalışır ve bu değerin belirtilen zamanda var olduğunu gösterir.

Terminal window
# Anahtarla: tek bir kaydın kanıt hash'ini yeniden hesaplayın (kanonik payload payload.json içinde, sonda satır sonu yok)
openssl dgst -sha256 -hmac "$TENANT_SECRET_KEY" payload.json

Eski kayıtlar (hash_version: 1), SHA-256( json(payload with sorted top-level keys) || key ) kullanır ve kişisel verileri doğrudan payload içinde barındırır.

timestamps.tsv, token başına bir satır içerir:

<file.tsr> <kind> <stamped data> <provider> <level at issuance>

Damgalanan veri küçük harfli bir hex dizesidir: bir kaydın proof_hash değeri, bir Merkle kökü veya package_hash. Zaman damgası otoritesi, bu dizenin ASCII karakterlerinin SHA-256 değerini, sonda satır sonu olmadan imzalamıştır:

Terminal window
printf '%s' "<stamped data>" > data.txt
openssl ts -verify -data data.txt -in <file.tsr> -CAfile <tsa_root.pem>
  • TSA’nın kök sertifikası pakette yer almaz. Onu zaman damgası otoritesinin kendisinden edinin; verisini kontrol ettiğiniz tarafın sağladığı bir kök hiçbir şey kanıtlamaz.
  • Bazı otoritelerin token’ları, openssl ts -verify komutunun ESSCertID kontrolünden geçemez. Bunun yerine imzayı ve zinciri iki adımda doğrulayın:
Terminal window
openssl ts -reply -in <file.tsr> -token_out -out token.der
openssl cms -verify -inform DER -in token.der -CAfile <tsa_root.pem> \
-purpose timestampsign -binary -out tstinfo.der
openssl ts -reply -in <file.tsr> -text # "Message data" değerini damgalanan verinin SHA-256 değeriyle karşılaştırın

Düzeyi simulated olan bir satır, bir test zaman damgasıdır: .tsr dosyası yoktur ve delil değeri taşımaz.

Geçerli bir token, damgalanan değerin, o zaman damgası otoritesine göre, token’daki zamandan daha geç olmayan bir anda var olduğunu gösterir. Belirli bir otoritenin zaman damgalarının hukuki bir karine taşıyıp taşımadığı (örneğin eIDAS kapsamındaki nitelikli zaman damgaları veya Türk hukuku kapsamında yetkili bir sağlayıcının zaman damgaları) otoriteye ve yargı çevresine bağlıdır.

Kayıtlara gruplar hâlinde zaman damgası vurulduğunda, tek bir token bir grubun Merkle kökünü kapsar ve her kayıt bir dahil edilme kanıtı alır. merkle_proofs.tsv:

<consent_id> <leaf> <index> <leaf_count> <root> <epoch.tsr> <path>

Ağaç, HashEntry’nin kendi SHA-256 ikili Merkle şemasıdır. RFC 6962 (Certificate Transparency) ağacı değildir ve RFC 6962 araçları onu doğrulamaz:

  • yaprak = kaydın proof_hash değeri (64 küçük harfli hex karakter), ek bir hash’leme olmadan;
  • düğüm = 128 ASCII karakteri olan hex(left) || hex(right) üzerinden SHA-256 — ham baytlar değil, hex dizeleri;
  • tek sayıda düğümü olan bir katman, son düğümünü çoğaltır;
  • yaprak/düğüm alan ayrımı (domain separation) öneki yoktur.

Bir yolu doğrulamak için cur = leaf ile başlayın ve her adımı uygulayın:

L:<h> → cur = sha256(<h> || cur)
R:<h> → cur = sha256(cur || <h>)
Terminal window
# tek bir adım, örn. "R:<h>"
cur=$(printf '%s%s' "$cur" "$h" | sha256sum | cut -d' ' -f1)

Sonuç <root> değerine eşit olmalıdır. Ayrıca 0 <= index < leaf_count koşulunu ve adım sayısının leaf_count için ağaç derinliğine eşit olduğunu kontrol edin — çoğaltma kuralı ağaç boyutunu köke bağlamaz, dolayısıyla bu değerler kanıtın bir parçasıdır. Son olarak <epoch.tsr> dosyasını 3. bölümdeki gibi <root> değerine karşı doğrulayın: kökün, dolayısıyla kaydın kanıt hash’inin ne zaman var olduğunu kanıtlayan budur.


KontrolOrtaya koyduğu
Sağlama toplamlarıPaket dosyaları kendi içinde tutarlıdır.
Kanıt hash’i (anahtarla)Kaydın içeriği, yazıldığı sırada hesaplanan hash ile eşleşir.
RFC 3161 token’ıDamgalanan değer, o otoriteye göre, token’ın zamanından daha geç olmayan bir anda vardı.
Merkle kanıtı + epoch token’ıKaydın kanıt hash’i, kökü o zamanda var olan bir grubun parçasıydı.

Ortaya koymadıkları: kişinin kim olduğu (bkz. Doküman Onayı ve İmza sayfasındaki identity_assurance) veya kaydın en başta doğru şekilde oluşturulmuş olduğu. Zaman damgası token’ı olmayan kayıtlar yalnızca kanıt hash’ine, dolayısıyla anahtarın gizliliğine dayanır.