# اشتقاق المفاتيح من القياسات الحيوية للهوية اللامركزية باستخدام المستخلِصات الضبابية

> السؤال هو: ماذا لو كانت سمتك الحيوية، مثل 'وجهك'، هي مفتاحك الخاص؟ لا عبارات استرداد تفقدها، ولا كلمات مرور تنساها، ولا مفاتيح تخزّنها. سمتك الحيوية تولّد محفظتك، التي تحمل اعتماداتك القابلة للتحقق، والتي تثبتها باستخدام ZKPs.

بقلم Shodipo Ayomide، نُشرت في 21 أكتوبر 2025. نسخة الويب: https://blog.shodipoayomide.com/ar/biometric-bound-key-derivation-for-decentralized-identity-using-fuzzy-extractors

![اشتقاق مفاتيح مرتبطة بالقياسات الحيوية لـ DID باستخدام المستخلِصات الضبابية](https://blog.shodipoayomide.com/banners/biometric-bound-key-derivation-for-decentralized-identity-using-fuzzy-extractors.png)

أنظمة الهوية اليوم تفرض قدرًا هائلًا من الثقة في الشركات لتخزين بياناتك بأمان. فعدة مزوّدين لخدمات KYC يحتفظون ببياناتك إلى أجل غير مسمّى. وكل تطبيق يحصل على تفاصيلك الكاملة حتى عندما لا يحتاج إلا إلى معرفة أن عمرك يتجاوز 18+ عامًا، وهذا قدر مفرط من المعلومات يُشارَك ويُترك مبعثرًا في كل مكان.

تعالج الهوية ذاتية السيادة **SSI** هذه المشكلة بمنحك التحكم في اعتماداتك، فيمكنك مشاركة ما هو ضروري فقط، وإثبات الادعاءات دون كشف البيانات. فالاعتمادات القابلة للتحقق **VC** تتيح لك في الأساس إثبات أنك تجاوزت 18+ عامًا دون إظهار تاريخ ميلادك الدقيق. لكن لدى **SSI** مشكلة - أين تخزّن المفاتيح الخاصة التي تتحكم في هويتك؟

هناك الكثير من الحلول الجوهرية لهذه المشكلة، وأحدها `biometric crypto identities`، وهو ليس من الحلول الشائعة، والسؤال هو: ماذا لو كانت سمتك الحيوية `biometric`، مثل وجهك `face`، هي مفتاحك الخاص `private-key`؟ لا عبارات استرداد `seed phrases` تفقدها، ولا كلمات مرور `passwords` تنساها، ولا مفاتيح `keys` تخزّنها. سمتك الحيوية `biometric` تولّد محفظتك `wallet`، التي تحمل اعتماداتك القابلة للتحقق، والتي تثبتها باستخدام ZKPs.

وهذا ممكن عبر `fuzzy extractors` + `zero-knowledge proofs`. وإليك طريقة عمله.

## المشكلة الفعلية التي يمكن أن يحلها هذا

صُمّمت الأنظمة التشفيرية التقليدية للتعامل مع بتّات قابلة لإعادة الإنتاج. لكن القياسات الحيوية تكسر قاعدتين أساسيتين تعتمد عليهما هذه الأنظمة:

**يجب أن تكون المفاتيح قابلة لإعادة الإنتاج بشكل تام** - فهي تتطلب إعادة إنتاج المفتاح بدقة على مستوى البت. ويجب أن يكون مفتاحك الخاص لتوقيع المعاملات متطابقًا في كل مرة على الإطلاق. لكن القياسات الحيوية مشوّشة، وهناك الكثير من المتغيرات التي يجب مراعاتها. فمسح بصمة إصبعك اليوم لن يطابق مسح الأمس بتًّا ببت بسبب اختلافات المستشعر، وطريقة وضع الإصبع، والرطوبة، ودرجة الحرارة - والقائمة تطول وتطول. والأمر نفسه ينطبق على مسح الوجه، وأنماط القزحية، وأي قياس بيولوجي.

**يجب أن تكون المفاتيح عشوائية بتوزيع منتظم** - يفترض الأمان التشفيري أن مفتاحك مسحوب عشوائيًا بتوزيع منتظم من فضاء المفاتيح بأكمله. لكن البيانات الحيوية لها بنية وأنماط. فقزحيتك ليست عشوائية بتوزيع منتظم، بل لها قيود بيولوجية، وأوجه تشابه على مستوى السكان، وإنتروبيا مركّزة في سمات بعينها.

وهذا يخلق مشكلة الدجاجة والبيضة المعتادة: لا يمكنك استخدام القياسات الحيوية مباشرة كمفاتيح **فهي مشوّشة جدًا**، ولا يمكنك تخزينها بأمان **فهي معلومات تعريف شخصية (PII) وغير قابلة للتغيير**، ولا يمكنك ببساطة تجزئتها **فالتشويش يكسر دوال التجزئة** كما تعلم. فماذا تفعل إذن؟

والآن إلى بيت القصيد!

## ما هي المستخلِصات الضبابية (Fuzzy Extractors)؟

انظر إلى المستخلِصات الضبابية على أنها تشفير مصحّح للأخطاء مخصص للبيانات المشوّشة. وهي زوج من الخوارزميات، `Gen` *للتوليد* و `Rep` *لإعادة الإنتاج*، تفعل شيئًا مثيرًا جدًا:

$Gen(w) \rightarrow (R, P)$ - تأخذ مدخلك الحيوي المشوّش `w`، وتُخرج سلسلة عشوائية بتوزيع منتظم `R` **وهي المفتاح التشفيري الفعلي** وسلسلة مساعدة عامة `P`. وإليك حقيقة ممتعة أخرى: يمكن نشر `P` علنًا دون المساس بالأمان. فهي لا تكشف أي معلومة ذات معنى عن سمتك الحيوية على الإطلاق.

$Rep(w', P) \rightarrow R$ - تأخذ قراءة حيوية مختلفة `w'` وسلسلة المساعدة العامة نفسها `P`، وتعيد إنتاج `R` نفسه تمامًا ما دامت `w'` **قريبة بما يكفي** من `w` الأصلية. أعلم أن هذا مخيف، لكن **القرب الكافي** في هذه الحالة يُقاس بالمسافة في فضاء متري ما **مسافة Hamming للسلاسل الثنائية، ومسافة التحرير للتسلسلات، وفرق المجموعات لمتجهات السمات**.

ضمان الأمان هنا قائم على نظرية المعلومات، فحتى مع معرفة `P`، يكون المفتاح المستخلَص `R` قريبًا بمقدار $\varepsilon$ من التوزيع المنتظم ما دامت لسمتك الحيوية إنتروبيا دنيا $\geq m$. ولا حاجة إلى أي افتراضات بشأن الصعوبة الحسابية. فالخصم الذي يملك قدرة حوسبة غير محدودة لا يزال عاجزًا عن تمييز  `R` من مفتاح عشوائي حقيقي بأفضلية تتجاوز $\varepsilon$.

الرياضيات هنا جميلة. بالنسبة إلى مستخلِص ضبابي بالمعاملات $(m, \ell, t, \varepsilon)$:

- $m$ = الإنتروبيا الدنيا لمدخلك الحيوي **بتّات عدم القابلية للتنبؤ**
- $\ell$ = طول المفتاح المستخلَص `R`
- $t$ = حد التسامح مع الأخطاء **إلى أي مدى يمكن أن تختلف `w'` عن `w`**
- $\varepsilon$ = المسافة الإحصائية عن التوزيع المنتظم **معامل الأمان**

## كيف يعمل هذا فعلًا

تستخدم البنية عنصرين أوليين يعملان معًا:

### المخططات الآمنة $(SS, Rec)$

المخطط الآمن يشبه الالتزام الضبابي. فـ $SS(w) \rightarrow s$ تُخرج مخططًا `s` يكشف من المعلومات ما يكفي لتصحيح الأخطاء فقط، لكنه أبعد ما يكون عن الكفاية لإعادة بناء `w` نفسها. ثم تستعيد $Rec(w', s) \rightarrow w$ قيمة `w` الأصلية من `w'` المشوّشة باستخدام المخطط.

بالنسبة إلى السلاسل الثنائية مع مسافة Hamming، تكون بنية المتلازمة (Syndrome Construction) هي الأمثل:

```python
class SyndromeSketch:
    def __init__(self, n, k, t):
        self.n, self.k, self.t = n, k, t
        self.syn_matrix = generate_bch_syndrome_matrix(n, k)

    def sketch(self, w):
        return np.dot(self.syn_matrix, w) % 2

    def recover(self, w_prime, s):
        s_prime = np.dot(self.syn_matrix, w_prime) % 2
        error_syn = (s_prime - s) % 2
        e = bch_decode(error_syn, self.t)
        return (w_prime - e) % 2
```

ما الذي يحدث هنا:

- تحسب `sketch()` متلازمة السمة الحيوية `w`، وتُخرج `s` بطول `$n-k$` بت
- تصحّح `recover()` الأخطاء في `w_prime` المشوّشة باستخدام المخطط `s`
- فقدان الإنتروبيا يساوي تمامًا طول المخطط `$n-k$` بت
- بالنسبة إلى شيفرة `BCH` الموسّعة $(128, 64, 22)$ **شيفرات Bose–Chaudhuri–Hocquenghem**: تخسر 64 بت، وتصحّح حتى $t = \lfloor(22-1)/2\rfloor = 10$ أخطاء

### والآن، من المخطط إلى المستخلِص

بعد تصحيح الأخطاء، تجزّئ السمة الحيوية المستعادة لاستخلاص مفتاح بتوزيع منتظم، على سبيل المثال

```rust
pub fn fuzzy_gen(biometric: &[u8]) -> (Vec<u8>, Vec<u8>) {
    let sketch = secure_sketch(biometric);
    let seed: Vec<u8> = (0..32).map(|_| rng.gen()).collect();
    let key = extract_key(biometric, &seed);
    let helper = [sketch, seed].concat();
    (key, helper)
}

pub fn fuzzy_rep(noisy_biometric: &[u8], helper: &[u8]) -> Vec<u8> {
    let (sketch, seed) = split_helper(helper);
    let recovered = sketch_recover(noisy_biometric, sketch);
    extract_key(&recovered, &seed)
}
```

الدالة `fuzzy_gen()`:

- تنشئ مخططًا من السمة الحيوية
- تولّد بذرة عشوائية لدالة التجزئة
- تستخلص المفتاح باستخدام `hash(biometric || seed)`
- تُرجع `key, helper` حيث helper = `sketch, seed`

الدالة `fuzzy_rep()`:

- تستعيد السمة الحيوية الأصلية من المسح المشوّش باستخدام المخطط
- تطبّق دالة التجزئة نفسها مع البذرة نفسها
- تُنتج المفتاح المطابق نفسه!

بالنسبة إلى القياسات الحيوية المعتادة:

- القزحية: شيفرة خام بطول 2048 بت **~249 بت من الإنتروبيا الفعلية**، ونسبة خطأ 10-30% ← استخلاص **مفاتيح بطول 40-105 بت**
- بصمة الإصبع: 20-80 نقطة تفصيلية (minutiae) **~50-150 بت**، وتشويش عالٍ ← استخلاص **مفاتيح بطول 8-40 بت**
- الوجه: تضمين (embedding) بـ 512 بُعدًا **20-60 بت من الإنتروبيا الفعّالة**

> ملاحظة: تحتوي التمثيلات الحيوية الخام على تكرار وارتباطات. فشيفرات القزحية تُظهر نسبة ~8:1 بين البتّات الخام (2048) والإنتروبيا وفق نظرية المعلومات (~249 بت). ويجب أن يحترم استخلاص المفتاح الإنتروبيا الفعلية، لا حجم التمثيل.

## لعبة الهوية
![](https://i.ibb.co/MyZNpbG3/Screenshot-2025-10-21-at-4-02-19-PM.png)

يضم نموذج الثقة في SSI ثلاث جهات فاعلة:

- صاحب الهوية - أنت، مع محفظة تحتوي على الاعتمادات
- المُصدِر - مصدر الثقة (جهة حكومية، أو جامعة، أو مزوّد KYC)
- المُتحقِّق - مستهلك الثقة (dApps، والعقود الذكية)
- الثقة في العالم الحقيقي - الجسر بين المُصدِر والمُتحقِّق

التدفق الكامل:
**السمة الحيوية ← المحفظة ← الاعتمادات ← براهين ZK ← هوية موثّقة**

![](https://i.ibb.co/WpHYM9Fq/image.png)

لنلقِ نظرة عليه خطوة بخطوة:

### من السمة الحيوية إلى المحفظة

```javascript
async function biometricToWallet(rawBiometric) {
    const binary = await preprocessBiometric(rawBiometric);
    const { key, helper } = await fuzzyExtractor.gen(binary);

    const expandedKey = await hkdf(
        key,
        128,
        'bip39-seed',
        await crypto.getRandomValues(new Uint8Array(32))
    );

    const mnemonic = bip39.entropyToMnemonic(expandedKey);
    const seed = await bip39.mnemonicToSeed(mnemonic);
    const master = bip32.fromSeed(seed);

    return {
        btc: deriveBitcoin(master),
        eth: deriveEthereum(master),
        sol: deriveSolana(seed),
        helper,
        salt
    };
}
```

العملية:

- معالجة مسبقة للسمة الحيوية ← متجه ثنائي **شيفرة القزحية، أو تضمين الوجه، وغير ذلك**
- تشغيل `fuzzy_gen()` ← الحصول على مفتاح بطول 40-128 بت + سلسلة مساعدة عامة
- التحويل إلى عبارة `BIP39` ← اشتقاق بذرة محفظة HD
- اشتقاق العناوين لـ BTC `P2WPKH`، و ETH `EVM`، و SOL `Ed25519`
- إرجاع العناوين + سلسلة المساعدة + الملح **وتخزينها كلها علنًا!**

بالنسبة إلى Solana تحديدًا، فهي تستخدم **منحنى مختلفًا**:

```javascript
import { derivePath } from 'ed25519-hd-key';

const solSeed = derivePath("m/44'/501'/0'/0'", seed.toString('hex')).key;
const solKeypair = Keypair.fromSeed(solSeed);
const solAddress = solKeypair.publicKey.toBase58();
```

> ملاحظة: تستخدم Solana `Ed25519`، لا `secp256k1`. لذا استخدم في تنفيذك `ed25519-hd-key` لتحقيق التوافق مع `SLIP-0010` **بما يطابق `Phantom` و `Solflare`**.

### الحصول على اعتماداتك القابلة للتحقق

محفظتك لديها الآن `DID`، لكن لإثبات أي شيء، تحتاج إلى اعتمادات قابلة للتحقق **VC**. وهنا يبدأ مثلث الثقة.
يتحقق المُصدِر من مستنداتك خارج السلسلة ويصدر برهانًا موقّعًا تشفيريًا:

```javascript
async function requestCredential(wallet, issuerEndpoint, claimData) {
    const connectionRequest = await issuerEndpoint.createConnection(wallet.did);
    
    const credentialOffer = await issuerEndpoint.offerCredential({
        type: 'KYCCredential',
        schema: 'https://schema.org/kyc-v1',
        claims: {
            country: claimData.country,
            birthYear: claimData.birthYear,
            verified: true
        }
    });
    
    const signedVC = await wallet.acceptCredential(credentialOffer);
    await wallet.storeCredential(signedVC);
    
    return signedVC;
}
```
ما الذي حدث:

- يتحقق المُصدِر من مستنداتك خارج السلسلة، مثل جواز السفر وصورة السيلفي وغير ذلك.
- يصدر `VC` موقّعة تشفيريًا (`cryptographically`) تتضمن ادعاءاتك
- تتضمن الـ `VC` توقيع `DID` الخاص بالمُصدِر الذي يثبت أصالتها
- تُخزَّن محليًا في محفظتك، لا على البلوك تشين
- عدة `VCs` من مُصدِرين مختلفين في التعليم والتوظيف و KYC

يحدد مخطط الاعتماد ما تحتويه الـ VC:
```json
{
  "@context": "https://www.w3.org/2018/credentials/v1",
  "type": ["VerifiableCredential", "KYCCredential"],
  "issuer": "did:polygonid:polygon:amoy:2qH7...",
  "issuanceDate": "2025-01-15T00:00:00Z",
  "credentialSubject": {
    "id": "did:polygonid:polygon:amoy:2qPz...",
    "birthYear": 1995,
    "country": "US",
    "kycVerified": true
  },
  "proof": {
    "type": "BJJSignature2021",
    "issuerData": {...},
    "signature": "0x..."
  }
}
```
والآن عندما يطلب منك مُتحقِّق أن **تثبت أن عمرك 18+**، تولّد ZKP من هذا الاعتماد.

### طبقة براهين المعرفة الصفرية

هنا يمكنك إثبات تفاصيلك الشخصية مثل **العمر، والجنسية، والشهادة الجامعية، والعنوان، وتاريخ الميلاد، وغير ذلك** دون كشف هذه البيانات الحساسة.

```javascript
async function proveAge(wallet, minAge) {
    const credential = await wallet.getCredential('kyc');
    const inputs = {
        birthYear: credential.birthYear,
        currentYear: 2025,
        minAge: minAge,
        signature: credential.signature
    };

    const { proof, publicSignals } = await snarkjs.groth16.fullProve(
        inputs,
        "ageCheck.wasm",
        "ageCheck.zkey"
    );

    return { proof, publicSignals };
}
```

ما الذي يُثبَت:

- أن عمر المستخدم يتجاوز `minAge` عامًا
- أن الاعتماد موقّع من مُصدِر موثوق
- ما لا يُكشف: العمر الفعلي، وتاريخ الميلاد، والاسم، وأي معلومات تعريف شخصية (PII)

دائرة Circom:

```circom
template AgeCheck() {
    signal input birthYear;
    signal input currentYear;
    signal input minAge;

    signal age <== currentYear - birthYear;

    component check = GreaterEqThan(16);
    check.in[0] <== age;
    check.in[1] <== minAge;
    
    signal output isValid;
    isValid <== check.out;
}
```

التحقق على السلسلة - `Solidity`:

```solidity
contract IdentityGate {
    mapping(address => mapping(uint256 => bool)) public verified;

    function submitProof(
        uint256 requestId,
        uint[2] calldata pA,
        uint[2][2] calldata pB,
        uint[2] calldata pC,
        uint[3] calldata pubSignals
    ) external {
        require(zkpVerifier.verifyProof(pA, pB, pC, pubSignals), "Invalid proof");
        require(pubSignals[2] >= minAge, "Age requirement not met");

        verified[msg.sender][requestId] = true;
        _grantAccess(msg.sender);
    }
}
```

العقد:

- يتحقق من برهان ZK تشفيريًا
- يفحص الإشارات العامة **DID الخاص بالمُصدِر، وحد العمر**
- يعلّم المستخدم على أنه موثّق
- ينفّذ منطق الأعمال **airdrop، أو الوصول إلى DAO، وغير ذلك**

إذن، من هذا التدفق يمكنك أن ترى كيف أصبحت سمتك الحيوية:

- **محفظتك** - متعددة السلاسل، وغير احتجازية، ودون عبارة استرداد
- **هويتك** - معرّف لامركزي `DID` مرتبط بسمتك الحيوية
- **اعتماداتك** - اعتمادات قابلة للتحقق `VC` من مُصدِرين موثوقين
- **خصوصيتك** - براهين المعرفة الصفرية `ZKP` لا تكشف شيئًا عنك

وهذه ليست أنظمة منفصلة متعددة - بل هي تدفق واحد موحّد. يحدث توليد المحفظة مرة واحدة أثناء التسجيل. ويمكن استخدام تدفق ZKP كلما احتجت إلى التحقق من الهوية. فكّر في الأمر هكذا: يمكنك استخدام محفظتك الحيوية تمامًا كأي محفظة عملات مشفرة أخرى للمعاملات العادية. لكن عندما يحتاج dApp إلى KYC أو إلى أي نوع من التحقق القائم على `PII` **مثل حالات استخدام `Polygon ID`**، تتدخل طبقة ZKP لإثبات الاعتمادات دون كشف بياناتك.

## بعض حالات الاستخدام الممكنة

1. **جوازات سفر الوكلاء:**

يمكن لكل وكيل ذكاء اصطناعي أن يمتلك `DID` مشتقًا من سمة حيوية. تخيّل وكيل تداول بالذكاء الاصطناعي يمتلك محفظته الخاصة واعتماداته الموثّقة:

```javascript
class TradingAgent {
    constructor(agentFingerprint) {
        this.wallet = await biometricToWallet(agentFingerprint);
        this.did = await createDID(this.wallet);
    }

    async trade(dex, params) {
        const proof = await this.proveReputation();
        return await dex.trade(params, proof);
    }
}
```

الوكيل:

- يشتق محفظته من سمته الحيوية `biometric` **تجزئة الشبكة العصبية**
- يثبت سمعته **1000+ صفقة ناجحة** عبر `ZKP`
- يعمل باستقلالية مع سجل أداء موثّق

تبني `SingularityNET` هذا بالضبط، وهو سجل ثقة لوكلاء الذكاء الاصطناعي يثبت فيه الوكلاء أصالتهم وسلامتهم وحالة تدقيقهم باستخدام اعتمادات قابلة للتحقق. ويتيح تدفق `biometric-wallet-ZKP` للوكلاء العمل بمفردهم مع الحفاظ على المساءلة.

2. **طبقة الهوية للـ dApps:**

يحتاج بروتوكول DeFi إلى KYC لكنه لا يريد تخزين بيانات المستخدمين **مسؤولية تنظيمية + مصيدة مغرية للمخترقين**:

```solidity
contract DeFiProtocol {
    modifier onlyKYCVerified() {
        require(identityGate.verified(msg.sender, KYC_ID), "KYC required");
        _;
    }

    function borrowUndercollateralized(uint256 amount) external onlyKYCVerified {
        _issueLoan(msg.sender, amount);
    }
}
```

لا يرى البروتوكول أبدًا جواز سفرك أو اسمك أو عنوانك. تحقّق الامتثال، وحُفظت الخصوصية.

النمط نفسه ينطبق على:

- التصويت في DAO **إثبات العضوية، لا الهوية**
- عمليات Airdrop **إثبات أنك إنسان، ومنع الروبوتات**
- بوابات العمر **إثبات 18+، لا العمر الدقيق**

3. **تسجيل دخول دون كلمة مرور في Web2**

```javascript
async function login(website) {
    const { key } = await fuzzyExtractor.rep(biometric, helper);
    const siteKey = deriveKey(key, website.domain);
    const signature = sign(challenge, siteKey);
    await website.verify(signature);
}
```

يحصل كل موقع على مفتاح مشتق فريد. لا كلمة مرور تُرسَل، ولا بيانات اعتماد يمكن اصطيادها.

4. **المدفوعات الحيوية:**

سمتك الحيوية هي التي تفوّض المعاملة:

```javascript
async function pay(merchant, amount) {
    const wallet = await biometricToWallet(scan);

    if (amount > 1000) {
        await merchant.verifyProof(generateKYCProof(wallet));
    }

    await wallet.sendTransaction({ to: merchant.address, value: amount });
}
```

تطبّق [BMONI](https://bmoni.com) + `BKey` هذا حاليًا، إذ تُشتق محافظك كلها بالكامل من سمتك الحيوية "**وجهك**"، وتُجهَّز المحافظ عبر سلاسل EVM ورموز محددة، وكل ذلك عبر وجهك!

5. **قاعدة بيانات لمنع الاحتيال:**

```solidity
contract AML {
    bytes32 public scamMerkleRoot;

    function checkClean(address wallet, bytes32[] calldata proof) public view returns (bool) {
        bytes32 hash = keccak256(abi.encodePacked(wallet));
        return !MerkleProof.verify(proof, scamMerkleRoot, hash);
    }
}
```

تستعلم الـ dApps قبل السماح بالوصول. يُحظر المحتالون المعروفون على مستوى الشبكة بأكملها، ويُرصد أيضًا من لديهم سجل من النشاط الغريب، بينما يتلقى المُدمِجون إشعارًا بالنشاط المشبوه السابق.

## التكاملات للمطورين

يحتاج البناء باستخدام الهويات الحيوية إلى بنية تحتية. وتوفر المنظومة ثلاثة مكوّنات أساسية:

### عقدة المُصدِر (Issuer Node)

تشغّل المؤسسات عُقد مُصدِر مستضافة ذاتيًا لإصدار الاعتمادات:

```bash
docker-compose up -d
make import-private-key-to-kms private_key=<eth-key>

# access the ui at localhost:8088
# access the api at localhost:3001
```

الميزات:

- إنشاء `DID` للمُصدِر
- تعريف `schemas` الاعتمادات
- إصدار `VCs` وإلغاؤها
- إدارة اتصالات المستخدمين
- نقل الحالة على السلسلة **Polygon**

مثال على الـ API:

```javascript
const issuerAPI = new IssuerNode({
    url: 'https://issuer.example.com',
    auth: { user: 'admin', password: 'secure' }
});

await issuerAPI.createIdentity({
    blockchain: 'polygon',
    network: 'amoy',
    method: 'polygonid'
});

await issuerAPI.issueCredential({
    did: 'did:polygonid:...',
    schema: 'KYCCredential',
    claims: { ageOver: 18 }
});
```

**منظومة الأدوات**

- Schema Builder: أنشئ مخططات VC مخصصة على `tools.privado.id/builder`
- Query Builder: صمّم استعلامات ZKP على `tools.privado.id/query-builder`
- Schema Explorer: تصفّح `schemas` المجتمع
- Marketplace: اكتشف `issuers` الاعتمادات

## بعض التحديات التقنية وحلولها

1: **تباين القياسات الحيوية**

تتباين بصمة إصبعك بنسبة 10-15% بين عمليات المسح. الحل: شيفرات `BCH` هي الأمثل لتصحيح الأخطاء على مستوى البت. بالنسبة إلى شيفرة قزحية بطول 2048 بت **تحتوي على ~249 بت من الإنتروبيا الفعلية** مع نسبة أخطاء 10% (~205 أخطاء في البتّات):

- استخدم شيفرة BCH $[2048, 1122, 341]$ فوق $GF(2^{11})$ - تصحّح حتى 170 خطأً في البتّات
- فقدان الإنتروبيا، $2048 - 1122 = 926$ بت (طول المخطط)
- الإنتروبيا المتبقية، $249 - (926 / 8.2) \approx 136$ بت من الإنتروبيا الفعّالة
- استخلص مفتاحًا بطول 128 بت **تقدير متحفظ، يأخذ فقدان الإنتروبيا في الحسبان**

**تمييز جوهري**: الـ 2048 بت هي تمثيل شيفرة القزحية الخام **مخرجات خوارزمية Daugman**. أما الإنتروبيا الفعلية وفق نظرية المعلومات فلا تتجاوز ~249 بت بسبب الارتباطات البيولوجية والتكرار **بنسبة ~8:1**.

2: **تقادم القالب**

المشكلة: يتغير وجهك مع مرور الوقت **التقدم في العمر، والوزن، وشعر الوجه، وغير ذلك**

الحل: إعادة تسجيل دورية مع ترحيل المفتاح:

```javascript
async function migrate(oldBio, newBio) {
    const oldWallet = await recover(oldBio);
    const { newWallet, newHelper } = await enroll(newBio);
    await oldWallet.transferAll(newWallet.address);
    await storage.update(newHelper);
}
```

أعِد التسجيل كل 2-3 سنوات للوجه، وكل 5 سنوات للقزحية، وسنويًا للصوت، وهكذا.

3: **كشف الحيوية (Liveness Detection)**

المشكلة: لا ينبغي أن يتمكن المهاجمون الذين يملكون صورتك من الوصول إلى محفظتك.

الحل: فحوصات الحيوية أثناء التقاط السمة الحيوية:

```javascript
const checks = await Promise.all([
    depthSensor.measure(),
    motionDetector.verify(['blink', 'nod']),
    thermalCamera.capture(),
    videoAnalyzer.checkTemporal()
]);
```

يفعل Orb الخاص بـ WorldCoin ذلك مع مسح القزحية: 25+ فحصًا للحيوية، وتصوير ثلاثي الأبعاد، وكاميرات بالأشعة تحت الحمراء + RGB. ويعمل بشكل مذهل - معدل القبول الخاطئ $< 0.0001\%$.

4: **خصوصية سلسلة المساعدة**

هل تسرّب `P` التي شرحناها سابقًا معلومات حيوية؟ لا. وفق النظرية **Dodis et al.**، يعرف المهاجم على الأكثر $n-k$ بت **طول المخطط**، ويبقى المفتاح `R` عشوائيًا إحصائيًا. وبالنسبة إلى قزحيتنا: يعرف 408 بت، وتبقى 392 بت من الإنتروبيا.

## هل هو جاهز للإنتاج؟

القطع موجودة بالفعل:

- المستخلِصات الضبابية: مكتبة `CompFE` (MIT)، وتعمل على الأجهزة المحمولة
- براهين ZK: BKey و Privado ID وغيرها تعمل على الشبكة الرئيسية
- العتاد: محفظة D'CENT، و FaceID، ومستشعرات البصمة موجودة في كل مكان
- المعايير: W3C DIDs، و VCs، و WebAuthn
- الشبكات: BTC و ETH و Polygon و Solana كلها تدعم محافظ HD **BIP32/39/44 منذ 2013**

ما الذي ينقص؟ التكاملات...

## مثال على تنفيذ في بيئة الإنتاج

إليك كيف يبدو استخدام هذا النظام فعليًا في بيئة الإنتاج

```javascript
async function enrollUser() {
    const bio = await captureLive();
    const { key, helper } = await fuzzyExtractor.gen(bio);

    const salt = await crypto.getRandomValues(new Uint8Array(32));
    const expandedKey = await hkdf('sha256', key, salt, 'bip39-seed', 128/8);
    const wallet = await deriveWallet(expandedKey);

    const did = await createDID(wallet.eth);
    const kycCred = await requestKYC(did, { passport, selfie });

    await storage.save({ helper, salt, did, credentials: [kycCred] });
    return { wallet, did };
}

async function accessDApp(dappURL) {
    const bio = await captureLive();
    const { helper, salt } = await storage.getHelperData();
    const key = await fuzzyExtractor.rep(bio, helper);

    const expandedKey = await hkdf('sha256', key, salt, 'bip39-seed', 128/8);
    const wallet = await deriveWallet(expandedKey);

    const proof = await generateProof(wallet, dappURL.request);
    await submitProof(wallet, proof, dappURL.verifier);

    await dappURL.grantAccess(wallet.address);
}

async function sendPayment(recipient, amount) {
    const bio = await captureLive();
    const { helper, salt } = await storage.getHelperData();
    const key = await fuzzyExtractor.rep(bio, helper);

    const expandedKey = await hkdf('sha256', key, salt, 'bip39-seed', 128/8);
    const wallet = await deriveWallet(expandedKey);

    await wallet.send({ to: recipient, value: amount });
}
```

يتعايش تدفق المحفظة العادي مع تدفق الهوية. ولا يظهر ZKP إلا عند الحاجة إلى التحقق، سواء من أجل KYC أو أي تحقق قائم على `PII` مثل العمر، والجنسية، والشهادة الجامعية، والعنوان، وتاريخ الميلاد، وغير ذلك. 

سمتك الحيوية هي مفتاحك، ومحفظتك هي هويتك عبر جميع السلاسل المدعومة، ولن تضطر أبدًا إلى القلق من فقدان عبارة الاسترداد أو المفاتيح الخاصة، فكل شيء مرتبط بسماتك الجسدية، وفي تنفيذ BMoni هي وجهك!

## روابط أساسية

- [مسح شامل للمستخلِصات الضبابية](https://www.cs.bu.edu/~reyzin/papers/fuzzysurvey.pdf) - Dodis و Reyzin و Smith
- [المستخلِصات الضبابية (SIAM)](https://epubs.siam.org/doi/10.1137/060651380)
- [مستخلِصات ضبابية فعّالة قابلة لإعادة الاستخدام من LWE](https://www.cs.umd.edu/~jkatz/papers/reusable-FE.pdf) - بنى مقاومة للحوسبة الكمومية
- [CompFE](https://github.com/benjaminfuller/CompFE)
- [Polygon ID SDK](https://github.com/0xPolygonID) - نظام هوية قائم على ZKP
- [أمان BMoni](https://bmoni.com/security/#22patents) - بنيتنا الأمنية
- [snarkjs](https://github.com/iden3/snarkjs) - مكتبة ZK-SNARK
