Verification (Doğrulama) 🎯
Bu kısımda Verifier
bireyinin rollerini birlikte gerçekleştireceğiz.
Bu işlemler:
- 📥
Claimer
tarafından verilenPresentation
objesini teslim alacağız. - 🧐 Veri içerisindeki bilgilerin doğruluğunu kontrol edeceğiz.
- 🔗
attestation
işleminin doğru olup olmadığını zincirdeki hash değerini kontrol ederek onaylayacaksın. Bu attestationrevoke
da edilmiş olabilir. Bu duruma da bakmak gerekir. - 🤔 Gönderilen kimlik belgesinin
Claimer
tarafından gönderildiğine emin olacaksın.
Presentation
yani türkçesi ile sunum yaptığımız belge credential
kullanılarak üretilecek belgedir. Bir presentation
credential
'in aksine içerisindeki belgelerin bazılarını saklayabilir. Bu bilgiler verifier
'lar tarafından bilinmesi gerekmeyen bilgilerdir. Bu presentation
aynı zamanda credential
'in Claimer
'a ait olduğunu kanıtlamaktadır.
🔍 Bir Claimer, onaylanmış bir Kimlik Bilgisini (Credential) aldığında, bunu cüzdanlarında saklayabilir. Ancak bu kimlik bilgisinin bir kopyası yoksa, geçerliliğini nasıl belirleyebiliriz?
🔒 KILT, bir Claimer tarafından bir kimlik bilgisinde sunulan bilgilerin doğruluğunu ve geçerliliğini bir Doğrulayıcıya (Verifier) doğrulama olanağı tanır.
💡 Doğrulayıcı, bu üçüncü tarafa ya doğrudan kendi itibarlarına dayanarak ya da Onaylayıcının dahil olduğu bir delegasyon yapısı aracılığıyla güven duyar.
✅ Doğrulama süreci için:
🔑 Claimer, kimlik bilgisi ve tanımlayıcılarıyla ilişkilendirilmiş özel anahtara ihtiyaç duyar.
🔒 Doğrulayıcı, güvendiği Onaylayıcının tanımlayıcısına ihtiyaç duyar.
🔎 Doğrulama süreci sırasında, Claimer, Doğrulayıcıya üç şeyi kanıtlamayı amaçlar:
1️⃣ Kimlik bilgisi geçerlidir ve Onaylayıcı tarafından iptal edilmemiştir. 2️⃣ Kimlik bilgisinde belirtilen özellikler gerçekten Claimer'a aittir. 3️⃣ Kimlik bilgisi, belirli bir kullanım durumu için Doğrulayıcı için ilgili bilgileri içerir.
🎨 Presentation Oluşturma
Sadece Claimer'ı gönderip Verifier'ın doğrulmasını bekleyemez. Aynı zamanda bu credantial
ile birlikte o credantial
'in sahibi olduğunu kanıtlaması gerekmektedir. Bu sahipliği kanıtlamak için bir presentation
oluşturup imzalaması gerekmektedir.
📦 Paketlerin Eklenmesi:
import * as Kilt from '@kiltprotocol/sdk-js'
Bu satır, KILT SDK'sını projeye dahil eder. Bu SDK, KILT protokolü ile etkileşimde bulunmak için gerekli fonksiyonları ve sınıfları sağlar.
🛠 createPresentation
Fonksiyonu:
export async function createPresentation(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
challenge?: string
): Promise<Kilt.ICredentialPresentation> {
Bu fonksiyon, bir kimlik bilgisi sunumu oluşturmak için asenkron bir fonksiyondur. Üç parametre alır:
credential
: Doğrulayıcıya sunulacak olan kimlik bilgisi.signCallback
: Kimlik bilgisi sunumunun imzalanması için kullanılacak geri çağırma fonksiyonu.challenge
: Opsiyonel bir parametre. Bu, doğrulayıcının talep ettiği rastgele bir dizedir ve kimlik bilgisi sunumunun doğrulayıcı tarafından talep edildiğini doğrulamak için kullanılır.
Fonksiyon, bir ICredentialPresentation
nesnesi döndürür. Bu nesne, kimlik bilgisi sunumunun kendisidir.
🎨 Sunumu Oluşturma:
return Kilt.Credential.createPresentation({
credential,
signCallback,
challenge
})
Bu kısım, Kilt.Credential.createPresentation
fonksiyonunu kullanarak bir kimlik bilgisi sunumu oluşturur. Bu fonksiyon, yukarıda belirttiğimiz üç parametreyi alır ve bir kimlik bilgisi sunumu döndürür.
Şimdi kodun tamamına bakarak işlevini anlamak istersek:
import * as Kilt from '@kiltprotocol/sdk-js'
export async function createPresentation(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
challenge?: string
): Promise<Kilt.ICredentialPresentation> {
// Create the presentation from credential, DID and challenge.
return Kilt.Credential.createPresentation({
credential,
signCallback,
challenge
})
}
Özetle, bu kod, bir kimlik bilgisi sunumu oluşturmayı sağlar. Bu sunum, bir doğrulayıcıya kimlik bilgisi sunarken kullanılır. Doğrulayıcı, bu sunumu kullanarak kimlik bilgisinin geçerliliğini ve kimlik bilgisi sahibinin kimliğini doğrulayabilir.
Verify (Onaylama)
Hadi verification
kodumuzu yazalım. İlk olarak getChallange
adında bir fonksiyon oluşturarak Claimer
'ın imzalayarak credantial
'a sahip olduğunu kanıtlayacağız.
Sonrasında verifyPresentation
fonksiyonu ile gerçek doğrulama yani verification
işlemini gerçekleştireceğiz. Bu işlemler için verify.ts
dosyasını kullanacağız.
Paket ve Modül İçe Aktarmaları
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { createPresentation } from './claimer/createPresentation'
import { generateKeypairs } from './claimer/generateKeypairs'
import { generateLightDid } from './claimer/generateLightDid'
Bu bölümde gerekli modüller ve paketler içe aktarılıyor. Özellikle dotenv
kullanılarak ortam değişkenleri yükleniyor ve KILT SDK'sı ile diğer yardımcı fonksiyonlar dahil ediliyor. Belirtilen Paketleri daha öncesinde sırasıyla birlikte oluşturmuştuk.
Benzersiz Challenge Oluşturma
function getChallenge(): string {
return Kilt.Utils.UUID.generate()
}
Bu fonksiyon doğrulama süreci için benzersiz bir challenge oluşturur.
Sunumu Doğrulama Fonksiyonu
async function verifyPresentation(
presentation: Kilt.ICredentialPresentation,
challenge: string,
trustedAttesterUris: Kilt.DidUri[]
): Promise<boolean> {
Doğrulama işlemi için bir fonksiyon oluşturarak işleme başlayabiliriz. Bu fonksiyon içerisine 3 adet parametre alacak olup True
veya False
olmak üzere bir Promise
döndürecektir. Bu parametrelere bakılacak olunursa sırasıyla:
presentation
: Doğrulanacak kimlik bilgisi sunumu.challenge
: Doğrulayıcının (Verifier) gönderdiği benzersiz değer. Bu, kimlik bilgisi sunumunun doğrulayıcı tarafından talep edildiğini doğrulamak için kullanılır.trustedAttesterUris
: Güvendiğimiz onaylayıcıların (Attester) DID URI'lerinin listesi.
Bu fonksiyon bir credential presentation'u doğrular. Sunumun geçerli olup olmadığını, sahipliğini ve attestation'ın doğru olup olmadığını kontrol eder.
KILT API'sine Erişim:
Kilt.ConfigService.get('api')
Bu satır, KILT API'sine erişim sağlar.
Try Catch Yapısı
try {
.
.
.
} catch {
return false
}
Sonrasında devamında bizi ilk olarak bir try
catch
yapısı karşılar. Bu yapı attestationun
doğru olup olmadığını kontrol etmektedir. Eğer doğru değilse yapı catch
bloğuna yakalanır ve false
değeri ile attestation
'un zincirde olmadığı anlaşılır.
Sunumu Doğrulama:
const { revoked, attester } = await Kilt.Credential.verifyPresentation(
presentation,
{ challenge }
)
Try yapısının içerisine girildiğinde asıl doğrulamanın yapıldığı Kilt.Credential.verifyPresentation
fonksiyonu bizi karşılamaktadır. Bu fonskiyon içerisine 2 adet değişken almaktadır. Bunlar sunulan presentation
ve claimer
'ın doğru birey olduğunu kanıtlamak için challange
değerleridir.
Bu fonksiyon çıktı olarak 2 adet değer döndürür. Bu değerler attestation
'un revoke
edilip edilmediğini yani geçerliliğini yitirip yitirmediğini ifade eden değer olmaktayken diğer değer ise sunumu onaylayan attester
'ın kim olduğudur.
if (revoked) {
return false
}
Eğer revoke
değeri true
ise yani credenatial
geçerliliğini yitirmişse verification
değeri false
olarak çıktı verilir.
return trustedAttesterUris.includes(attester)
Bu satır, sunumu onaylayanın (attester
) güvendiğimiz onaylayıcı listesinde (trustedAttesterUris
) olup olmadığını kontrol eder. Eğer onaylayıcı bu listede ise, fonksiyon true
döndürür, aksi takdirde false
döndürür.
Bir Verifier'ın kontrol etmesi gereken en önemli niteliklerden biri bir attester
'a güvenip güvenmediğidir. Eğer güvenmiyorsa attestation
zincirde olsun olmasın belgeyi kabul etmeyebilir. Bu durum attesterlar
arasındaki güven yarışını oluşturur.
Doğrulama Akışı (Verification Flow)
export async function verificationFlow(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
trustedAttesterUris: Kilt.DidUri[] = []
) {
Bu fonksiyon, doğrulama sürecini yönetir. Öncelikle bir challenge oluşturur, ardından bir sunum oluşturur ve son olarak sunumu doğrular. Bu fonksiyonda içerisine 3 adet parametre almaktadır. Bu parametrelere teker teker bakılacak olunursa:
credential: Kilt.ICredential
: Doğrulayıcıya sunulacak olan kimlik bilgisi.signCallback: Kilt.SignCallback
: Kimlik bilgisi sunumunun imzalanması için kullanılacak geri çağırma fonksiyonu.trustedAttesterUris: Kilt.DidUri[]
: Doğrulayıcının güvendiği Onaylayıcıların (Attester) DID URI'lerinin listesi. Opsiyonel bir parametre ve varsayılan olarak boş bir liste ile başlar.
Aslında bu fonksiyonu oluşturarak tüm verification
işlemini tek bir yerde yönetmekteyiz.
verificationFlow
fonksiyonu, verifyPresentation
fonksiyonunu içeren daha geniş bir doğrulama sürecini temsil eder. Tek başına verifyPresentation
fonksiyonu sadece bir kimlik bilgisi sunumunun doğruluğunu kontrol eder. Ancak, gerçek dünyada bir doğrulama süreci, sadece sunumun doğruluğunu kontrol etmekten daha fazlasını gerektirir. İşte bu yüzden verificationFlow
fonksiyonuna ihtiyaç duyarız.
verificationFlow
fonksiyonunun amacı şunlardır:
Benzersiz Bir Challenge Oluşturma: Doğrulayıcı, Claimer'a benzersiz bir challenge gönderir. Bu, sunumun gerçek zamanlı olarak ve belirli bir talep için oluşturulduğundan emin olmak için kullanılır.
Sunumu Oluşturma: Claimer, bu challenge'ı kullanarak kimlik bilgisi sunumunu oluşturur ve imzalar.
Sunumu Doğrulama: Doğrulayıcı, Claimer'dan alınan sunumu
verifyPresentation
fonksiyonu ile doğrular.Sonuçları Bildirme: Sunum doğruysa, doğrulayıcı başarılı bir doğrulama mesajı yazdırır. Aksi takdirde, başarısız bir doğrulama mesajı yazdırır.
Bu adımların her biri, merkezi olmayan bir kimlik doğrulama sürecinin kritik bileşenleridir. verifyPresentation
fonksiyonu, bu sürecin sadece bir parçasıdır. verificationFlow
fonksiyonu, bu adımları bir araya getirerek tam bir doğrulama süreci sağlar. Bu nedenle, sadece verifyPresentation
fonksiyonuna değil, aynı zamanda bu adımları birleştiren verificationFlow
fonksiyonuna da ihtiyaç duyarız.
Benzersiz Challenge Oluşturma
const challenge = getChallenge()
Bu satır, Claimer'a gönderilmek üzere benzersiz bir challenge oluşturur. Bu, sunumun gerçek zamanlı olarak ve belirli bir talep için oluşturulduğundan emin olmak için kullanılır. Bu fonksiyonu önceden oluşturmuştuk.
Kimlik Bilgisi Sunumu Oluşturma
const presentation = await createPresentation(
credential,
signCallback,
challenge
)
Bu satır, verilen kimlik bilgisi, imza geri çağırma fonksiyonu ve challenge kullanarak bir kimlik bilgisi sunumu oluşturur. Bu fonksiyonu claimer
klasöründe birlikte oluşturmuştuk.
Sunumu Doğrulama:
const isValid = await verifyPresentation(
presentation,
challenge,
trustedAttesterUris
)
Bu satır, oluşturulan kimlik bilgisi sunumunu doğrular. Eğer sunum geçerliyse, isValid
değeri true
olacaktır.
Sonuçları Bildirme:
if (isValid) {
console.log('Verification successful! You are allowed to enter the club 🎉')
} else {
console.log('Verification failed! 🚫')
}
Bu kısım, sunumun doğruluğuna göre bir mesaj yazdırır. Eğer sunum doğruysa, başarılı bir doğrulama mesajı yazdırılır. Aksi takdirde, başarısız bir doğrulama mesajı yazdırılır.
verificationFlow()
fonksiyonunun içeriğine baktığımızda aslında önceden yazdığımız fonksiyonları çalıştırırız. Sırasıyla
- Claimer'ı onaylamak için bir
Challange
oluştururuz. - Claimer tarafından bir
presentation
oluştururuz. - Sunulan doğrulamayı
Verifier
olarak doğrularız.
Ana Fonksiyon
Bu bölüm bu dosyanın doğrudan çalıştırılması durumunda çalışacak olan ana fonksiyonu içerir. Ortam değişkenlerini yükler, KILT'a bağlanır ve doğrulama akışını başlatır.
if (require.main === module) {
;(async () => {
If yapısı ile modülün direkt olarak çalıştırılıp çalıştırılmadığını kontrol ederiz.
Ortam Değişkenlerinin Yüklenmesi:
envConfig()
Bu satır, .env
dosyasındaki ortam değişkenlerini yükler. Bu, projede kullanılan çeşitli yapılandırma değerlerini saklamak için kullanılır.
KILT'a Bağlanma:
await Kilt.connect(process.env.WSS_ADDRESS as string)
Bu satır, KILT ağına bağlanır. Bağlantı adresi .env
dosyasından alınır.
Claimer'ın DID Bilgilerini Oluşturma:
const claimerDidMnemonic = process.env.CLAIMER_DID_MNEMONIC as string
const { authentication } = generateKeypairs(claimerDidMnemonic)
const claimerDid = generateLightDid(claimerDidMnemonic)
Bu adımlar, Claimer'ın DID (Decentralized Identifier) bilgilerini oluşturmak için kullanılır. Bu, kimlik bilgisi sunumunu imzalamak için gereklidir.
Fark etmiş olabileceğiniz gibi Claimer'ın DID'sini sorgularken yeni bir Light DID
oluşturma fonksiyonu çalıştırdık. Bu durumun nedeni zincir üzerinde depolanmayan light DID
'lerin her seferinde yeniden oluşuturulmaya açık olmasıdır.
verificationFlow()
fonskiyonunun içerisinde presantation
oluşturma fonksiyonu da çalışmaktadır. Bu nedenle Claimer
bireyinin DID'sine ihtiyaç vardır.
Attester'ın DID Bilgilerini Yükleme:
const attesterDid = process.env.ATTESTER_DID_URI as Kilt.DidUri
Bu satır, Attester'ın DID URI'sini .env
dosyasından alır.
Kimlik Bilgisini Yükleme:
const credential = JSON.parse(process.env.CLAIMER_CREDENTIAL as string)
Bu satır daha önceden attestation
bölümünde kodumuzu çalıştırarak elde ettiğimiz ve .env
dosyası içerisine kaydettiğimiz Credantial
'ın kod içerisine eklenmesini sağlamaktadır.
Doğrulama Akışını Başlatma:
await verificationFlow(
credential,
async ({ data }) => ({
signature: authentication.sign(data),
keyType: authentication.type,
keyUri: `${claimerDid.uri}${claimerDid.authentication[0].id}`
}),
[attesterDid]
)
Bu satır, yukarıda tanımlanan verificationFlow
fonksiyonunu çağırarak doğrulama sürecini başlatır.
Hata Yakalama:
} catch (e) {
console.log('Error in the verification flow')
throw e
}
Bu kısım, doğrulama süreci sırasında herhangi bir hata oluşursa bu hatayı yakalar ve bir hata mesajı yazdırır.
Kodun bütününe bir arada bakarak yapılan işlemleri incelememiz gerekirse:
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { createPresentation } from './claimer/createPresentation'
import { generateKeypairs } from './claimer/generateKeypairs'
import { generateLightDid } from './claimer/generateLightDid'
function getChallenge(): string {
return Kilt.Utils.UUID.generate()
}
// Verifies validity, ownership & attestation.
async function verifyPresentation(
presentation: Kilt.ICredentialPresentation,
challenge: string,
trustedAttesterUris: Kilt.DidUri[]
): Promise<boolean> {
Kilt.ConfigService.get('api')
try {
const { revoked, attester } = await Kilt.Credential.verifyPresentation(
presentation,
{ challenge }
)
if (revoked) {
return false
}
// Returns true if no trusted attester URI is provided or, if it is, if it matches the one that issued the presented credential.
return trustedAttesterUris.includes(attester)
} catch {
return false
}
}
export async function verificationFlow(
credential: Kilt.ICredential,
signCallback: Kilt.SignCallback,
trustedAttesterUris: Kilt.DidUri[] = []
) {
// Verifier sends a unique challenge to the claimer 🕊
const challenge = getChallenge()
// Create a presentation and send it to the verifier 🕊
const presentation = await createPresentation(
credential,
signCallback,
challenge
)
// The verifier checks the presentation.
const isValid = await verifyPresentation(
presentation,
challenge,
trustedAttesterUris
)
if (isValid) {
console.log('Verification successful! You are allowed to enter the club 🎉')
} else {
console.log('Verification failed! 🚫')
}
}
// Don't execute if this is imported by another file.
if (require.main === module) {
;(async () => {
envConfig()
try {
await Kilt.connect(process.env.WSS_ADDRESS as string)
const claimerDidMnemonic = process.env.CLAIMER_DID_MNEMONIC as string
const { authentication } = generateKeypairs(claimerDidMnemonic)
const claimerDid = generateLightDid(claimerDidMnemonic)
const attesterDid = process.env.ATTESTER_DID_URI as Kilt.DidUri
// Load credential and claimer DID
const credential = JSON.parse(process.env.CLAIMER_CREDENTIAL as string)
await verificationFlow(
credential,
async ({ data }) => ({
signature: authentication.sign(data),
keyType: authentication.type,
keyUri: `${claimerDid.uri}${claimerDid.authentication[0].id}`
}),
[attesterDid]
)
} catch (e) {
console.log('Error in the verification flow')
throw e
}
})()
}
Sırasıyla işlevler:
- Paketler eklenir.
- Claimer'ın kendinin
credential
'a sahip olduğunu kanıtlamak için birchallange
oluşturulur. True
veFalse
şeklinde bir çıktı verenPresantation
onaylama fonksiyonu yazılır.- Baştan sona tüm işlemleri bir arada çalıştırmak için verificationFlow() fonksiyonu yazılır.
- Fonksiyonun tek başına çalışırken neler yapacağını belirten fonksiyon yazılır.
Kodu Çalıştıralım!
Kodu çalıştırmak için terminalde kilt-rocks
klasöründe bulunduğumuza emin olduktan sonra alt kısımdaki kodu çalıştırabiliriz:
yarn ts-node verify.ts
Tüm bireyleri tüm kodları ile birlikte çalıştırdın ve hallettin! Seninle gurur duyuyorum! Hadi birlikte KILT-SDK ile projeler gerçekleştirelim!