./research / verifiable-audit-layer
یک لایه حسابرسی تأییدپذیر برای هوش مصنوعی.
یک لایه حسابرسی که دستکاری را آشکار میکند، برای استنتاج مدل و اجرای عامل: سریالسازی متعارف، درهمسازی با تفکیک دامنه، امضاهای DSSE، یک Merkle DAG برای هر اجرا، و یک Merkle Mountain Range میاناجرایی که ثابت میکند هیچ اجرایی حذف نشده است. هر بدوی از یک محکزنی رودررو در برابر جایگزینهای واقعی انتخاب شد، با دادههای خام کامیتشده. این یادداشت همان طراحی و آزمایشهای پشت آن است.
مدل تهدید
حریفی را فرض میکنیم که ذخیرهسازی را در اختیار دارد و میتواند رکوردها را پس از وقوع بازنویسی کند، از جمله همان اپراتوری که آنها را تولید کرده است. هدف این است که هر ویرایش روی یک اجرای مهرشده قابل تشخیص باشد، رکورد در بازه نگهداریای که با سال اندازهگیری میشود تأییدپذیر بماند، و تأیید هیچ ورودی خصوصیای را افشا نکند. دو ویژگی سرتاسر جدا نگه داشته میشوند: یکپارچگی یک اجرای واحد، و کاملبودن مجموعه اجراها. یک رسید برای هر اجرا اولی را میدهد و درباره دومی چیزی نمیگوید، پس هر دو جداگانه مهندسی میشوند.
هر انتخاب زیر به یک شیوه انجام شد. ادعا نمیکنیم که یک بدوی بهترین است؛ آن را با جایگزینهای معتبر روی همان ماشین میسنجیم و داده خام را کامیت میکنیم، چنانکه هر عدد اینجا با یک فرمان بازتولید میشود. زمانها سریعترینِ چند اجرا پس از دور ریختن گرمکردن است، با نگه داشتن میانگین و انحراف معیار تا اندازهگیری ناپایدار بهجای پنهان شدن نشانهگذاری شود. اعداد از یک میزبان AMD64 روی CPython 3.14 آمدهاند و بهعنوان نسبت معنا دارند، نه بهعنوان مقادیر مطلق.
آزمایشها و نتایج
هر نقطهعطف یک آزمون رودررو در برابر جایگزینهای واقعی بود، نه یک اندازهگیری تنها. نمای کلی زیر است؛ نتایج دقیق هر یک در بخشهای بعد.
| نقطهعطف | آزموده در برابر | نتیجه |
|---|---|---|
| صورت متعارف | JSON سادهلوحانه، CBOR | JCS، بایتبهبایت یکسان، ~3x هزینه |
| درهمسازی | SHA-256، BLAKE3، keccak-256 | keccak بومی 17x، همان بایتها |
| هسته بومی | بکاندهای pip در برابر Rust | مهر 6x، ریشه بایتبهبایت یکسان |
| امضا | ECDSA، BLS، ML-DSA | Ed25519، 64 B، قطعی |
| پساکوانتومی | ML-DSA 44 / 65 / 87 | مرحلهای، تأیید همتراز، 38x اندازه |
| ردِ هر اجرا | 8 حمله جعل، سربار | همه گرفته شد، ~121 us / رویداد |
| گزارش میاناجرایی | بازسازی ساده Merkle | MMR، الحاق مسطح، 483x |
سریالسازی متعارف
یک کپسول باید در هسته Python ما، در کلاینت TypeScript ما، و در ابزار خودِ یک حسابرس به بایتهای یکسان درهم شود، وگرنه یک رکورد معتبر در تأیید شکست میخورد. ما از RFC 8785 (JSON Canonicalization Scheme) بهره میبریم که قالببندی اعداد، ترتیب کلیدها بر پایه واحد کد UTF-16، و رد مقادیر نامتناهی را تثبیت میکند. آن را در برابر JSON با کلیدهای مرتبشده سادهلوحانه و در برابر CBOR آزمودیم.
| رویکرد | Python در برابر Node | هزینه |
|---|---|---|
| JSON مرتب سادهلوحانه | در Unicode و اعداد واگرا میشود | خط پایه |
| RFC 8785 JCS | بایتبهبایت یکسان | حدود 3x هنگام سریالسازی |
| CBOR | دودویی، برای خواندن به رمزگشا نیاز دارد | فشرده |
JSON سادهلوحانه میان زمانهای اجرا در ترتیب Unicode و قالببندی اعداد واگرا میشود و ازاینرو تأیید میانزبانی را بیصدا میشکند. JCS در هر دو بایتبهبایت یکسان است، با حدود 3x زمان سریالسازی که یک بار بهازای هر درهم پرداخت میشود و در کنار درهمسازی و کار شبکهای پیرامون ناچیز است. دقیقاً یک پیادهسازی از آن را نگه میداریم. وقتی ماژول بومی ما سریالساز JSON خودش را آورد، آن را برداشتیم، چون یک متعارفساز دوم که روی ورودیهای معمول توافق دارد و روی حالتهای مرزیای که حریف میتواند برگزیند واگرا میشود، بدتر از هیچ است.
درهمسازی و هسته بومی
برگها با BLAKE3 و گرههای Merkle با keccak-256 درهم میشوند، هر دو با تفکیک دامنه RFC 6962 (پیشوندهای متمایز برای برگها و گرههای درونی) تا رده پیشتصویر دوم بسته شود، جایی که یک گره درونی بهجای برگ عرضه میشود. keccak-256 همان SHA3-256 نیست؛ این دو یک جایگشت مشترک دارند اما در یک بایت لایهگذاری تفاوت دارند، و تأییدگر رویزنجیره keccak میگوید، پس یک جایگزینی بیصدا هر ریشه را رویزنجیره به شکست میکشاند. بنابراین لایه درهمسازی الگوریتم درخواستشده را محاسبه میکند یا خطا میاندازد، هرگز یک همانند، و الگوریتم را در هر کپسول ثبت میکند تا یک تأییدگر تابع دقیق را بازتولید کند نه آنکه از آنچه بهطور محلی نصب است استنتاجش کند.
| بدوی، ورودی 64 B | گذردهی | یادداشت |
|---|---|---|
| SHA-256 (stdlib) | 1٫50M ops/s | خط پایه، همیشه حاضر |
| BLAKE3 (pip) | 1٫44M ops/s | همتراز با SHA-256 |
| keccak-256 (pip) | 99k ops/s | 15x کندتر، گلوگاه |
| keccak-256 (هسته Rust) | 1٫69M ops/s | 17x سریعتر از pip |
keccak پیادهسازیای در کتابخانه استاندارد ندارد، و همین ماژول بومی را ارزشمندِ ساختن کرد. شکاف در ورودیهای اندازهرویداد بیشترین است، چون هزینه pycryptodome آنجا تخصیص شیء بهازای هر فراخوان است نه درهمسازی، درست همان اندازهای که یک ردِ حسابرسی بیش از همه درهم میکند؛ سرتاسری، هسته بومی مهر یک اجرای 1000-رویدادی را از 78 به 491 مهر در ثانیه میرساند، حدود 6x. مهمتر: فعال کردن شتابدهنده نمیتواند نتیجه را عوض کند: مهر همان اجرا با و بدون crate ریشهای بیتبهبیت یکسان میدهد، یک مجموعه انطباق هر دو مسیر را در برابر بردارهایی که نویسندگان الگوریتم منتشر کردهاند میسنجد، و CI یک چرخ با ABI پایدار (abi3) میسازد و همان یک مصنوع را روی هر Python از 3.10 تا 3.14 تأیید میکند. نصب آن سرعت را عوض میکند و نه چیز دیگری.
امضاها برای رکوردی دهساله
امضا روی یک رکورد حسابرسی باید تا زمانی که رکورد قابل مناقشه است دوام آورد، و تعهدات ثبتگزارش هوش مصنوعی اکنون به سوی یک دهه میروند. اگر طرح درحالیکه رکورد هنوز در پنجره نگهداریاش است بشکند، حریف میتواند آن را جعل و تاریخش را به عقب بزند، پس کل بایگانی یکجا فرو میریزد. Ed25519 را در برابر ECDSA، BLS و خانواده پساکوانتومی NIST یعنی ML-DSA، در گذردهی و اندازهها محک زدیم.
| طرح | تأیید (ops/s) | اندازه امضا |
|---|---|---|
| ECDSA P-256 | 16 887 | ~72 B |
| ML-DSA-44 (پساکوانتومی) | 10 725 | 2420 B |
| Ed25519 | 10 375 | 64 B |
| BLS12-381 | فقط پیادهسازی مرجع | 96 B، تجمیع میکند |
دو نتیجه فرضهایی را که با خود آورده بودیم واژگون کرد، و هر دو را در سابقه نگه میداریم. Ed25519 سریعترین در تأیید نیست: ECDSA P-256 حدود 1٫6x سریعتر اندازهگیری شد، روی اسمبلی کتابخانهای بهینه. Ed25519 در اندازه امضا و در قطعیت (RFC 8032) پیشفرض میماند، که خرابیِ استفاده مجدد از nonce در ECDSA را برمیدارد، خرابیای که کلید خصوصی را نشت میدهد درحالیکه امضاها هنوز تأیید میشوند. و امضاهای پساکوانتومی در تأیید کند نیستند: ML-DSA-44 اندکی از Ed25519 پیشی گرفت، با هزینهاش در امضا کردن (حدود 13x کندتر) و در اندازه (حدود 38x بایت). چون یک رد یک بار امضا و سالها تأیید میشود، سمت گران همان سمتی است که کمترین بار انجامش میدهیم. BLS بر پایه یک الزام رد شد، نه بر پایه یک عدد: تجمیع امضاهای بسیار را در 96 بایت جمع میکند، اما یک تجمیع همهیاهیچ تأیید میشود و به هر کلید و پیام نیاز دارد، که با افشای یک شاخه از یک تصمیم بدون آشکار کردن بقیه ناسازگار است.
بازقاببندیای که اهمیت دارد: امضاها محرمانه نیستند، پس «اکنون برداشت کن، بعداً رمزگشایی کن» صدق نمیکند، و تهدید واقعی جعل پسنگرانه درون پنجره نگهداری است. لنگر انداختن یک ریشه به یک دفتر عمومی ثابت میکند یک رکورد چه هنگام وجود داشته، مستقل از طرح امضا، پس یک کلید شکسته توانِ اثبات چه کسی رکوردی را مهر کرده میستاند اما نه چه هنگام و نه چه چیزی را. پس لنگرانداختن روی مسیر بحرانی است و ML-DSA پشت آن مرحلهای چیده شده، با نگه داشتن پاکت DSSE چابکِ الگوریتمی و ثبت الگوریتم بهازای هر کپسول.
ردِ حسابرسی هر اجرا
هر اجرا دنبالهای از رویدادها با الحاقتنها و زنجیرشده با درهم است (فراخوانهای LLM، فراخوانهای ابزار، بازیابیها، زایش زیرعاملها، تأییدهای انسانی، تصمیمهای نرده محافظ)، با یک ریشه Merkle روی همه و یک امضای DSSE روی ریشه. تنها درهمهای ورودیها و خروجیها ذخیره میشوند، هرگز محمولهها، پس رد بهطور پیشفرض حریم خصوصی را پاس میدارد. تأییدگر تنها معتبر یا نامعتبر بازنمیگرداند؛ تضمینی را که شکسته نام میبرد.
| عملیات (اجرای 102-رویدادی) | هزینه | مقیاسپذیری |
|---|---|---|
| ثبت یک رویداد | ~121 us | مسطح، زیر 0٫01% یک گام |
| مهر، ساخت ریشه | 0٫15 ms | خطی در رویدادها |
| تأیید، بازمحاسبه همه برگها | 9٫2 ms | خطی، حدود 60x مهر |
ثبت کمتر از یکصدم درصد از یک گام عامل معمول است که رفتوبرگشت به مدل بر آن چیره است، پس سربار دلیلی برای نمونهگیری نیست و رد کامل میماند نه آماری. تأیید بسیار سنگینتر از مهر است چون هر برگ را از محتوا بازمحاسبه میکند درحالیکه مهر تنها درخت را روی درهمهایی که پیشاپیش حاضرند میسازد. آن ناتقارن برای یک ردِ حسابرسی درست است، جایی که ثبت ثابت و تأیید نادر است، و بازتأیید انبوه را همان جایی نشانه میگذارد که هسته بومی و موازیسازی در گام بعد بازده میدهند. برای ملموس کردن تضمینها، یک دمو به یک اجرای مهرشده هشتگونه حمله میکند، هر یک با دلیلی مشخص رد میشود:
| حمله | رد شد بهعنوان |
|---|---|
| بازنویسی یک خروجی مدل | ناهمخوانی درهم برگ |
| حذف یا درج یک رویداد | ناهمخوانی شمار رویدادها |
| بازچینش رویدادها | گسست زنجیره |
| بریدن اجرا | ناهمخوانی سر زنجیره |
| تنزل الگوریتم درهم | ناهمخوانی درهم برگ |
| ارائه زیر کلید نادرست | امضا تأیید نمیشود |
گزارش شفافیت میاناجرایی
یک کپسول معتبرِ هر اجرا نمیتواند ثابت کند که مجموعه اجراها کامل است. اپراتوری که یک اجرای ناخوشایند را کنار میگذارد، مجموعهای از کپسولهای تکبهتک بینقص و تاریخی سوراخدار در دست دارد. این را با یک گزارش الحاقتنهای واحد از ریشههای کپسول میبندیم که برهانهای شمول (یک اجرا در گزارش هست) و برهانهای سازگاری (گزارش در اندازه پیشین پیشوندی دقیق از گزارش اکنون است) را پشتیبانی میکند. سازگاری سانسور را میگیرد: گزارشی که با حذف یک اجرا بازسازی شده از درون خوشساخت است و هر کپسول بازمانده هنوز تأیید میشود، اما در یک بررسی سازگاری در برابر ریشهای که پیشتر منتشر شده شکست میخورد، و همان بررسی یک درج تاریخبهعقبزده را رد میکند. این تنها در برابر ریشهای که پیش از دستکاری کامیت شده کار میکند، پس آن ریشه باید جایی زندگی کند که اپراتور نتواند بازنگریاش کند، مانند یک لنگر عمومی.
ما از یک Merkle Mountain Range بهجای درخت Merkle ساده بهره میبریم، چون یک الحاق تنها گره میافزاید و هرگز هیچکدام را بازنویسی نمیکند، که میگذارد گزارش روی ذخیرهسازی یکبارنویس یا شیء زندگی کند و برهانهای شمول کهنه را با رشد گزارش معتبر نگه دارد. آن ویژگی نه صرفاً راحت که تقریباً بهینه است: ePrint 2025/234 ثابت میکند هر تعهد فشرده الحاقتنها باید شمار فراخطی از بهروزرسانیهای شاهد را برانگیزد، و یک گونه نزدیک از MMR در اساس به آن کران میرسد.
| اندازه گزارش | ساخت MMR | بازسازی ساده |
|---|---|---|
| 500 | 1٫3 ms | 158 ms (120x) |
| 1000 | 2٫6 ms | 618 ms (237x) |
| 2000 | 5٫2 ms | 2491 ms (483x) |
الحاق با رشد گزارش مسطح میماند (حدود 390k الحاق در ثانیه هم در 100 و هم در 10 000 مدخل) درحالیکه بازسازی یک درخت ساده در همان بازه از 8176 به 84 ریشه در ثانیه میافتد، همان امضای درجهدوم-در-برابر-خطیلگاریتمی. ذخیرهسازی روی 2٫00 درهم ذخیرهشده بهازای هر مدخل مینشیند و برهانهای شمول تنها از 7 به 17 گام میان 100 و 100 000 مدخل رشد میکنند. جایی که میبازیم: برهانهای سازگاری ما O(log^2 n) هستند، یک مسیر بهازای هر قله گزارش کهنه میبرند بهجای O(log n) دستیافتنی، چند کیلوبایت در 100 000 مدخل و یک بدهبستان عمدی برای ساختاری که یک بازبین با خواندن میتواند وارسیاش کند.
مرزهایی که از آنها نمیگذریم
درهمسازی گواهِ دستکاری میدهد، نه مصونیت از دستکاری. حریفی که یک اجرا را بازسازی و ریشهاش را بازمحاسبه میکند، رکوردی خودسازگار میسازد، چون ریشه Merkle ثابت میکند رویدادها با ریشه میخوانند، نه اینکه ریشه همان منتشرشده است. امضا این را میگیرد، و لنگر عمومی زمان را ثابت میکند. گزارش شفافیت در بزرگ بر همان فرض تکیه دارد: یک اجرای حذفشده را تنها نسبت به ریشهای که پیش از حذف کامیت شده تشخیص میدهد. این مرزها را در محصول و دموهایش اعلام میکنیم، و یک آزمون تصدیق میکند که دموی جعل همچنان حملهای را نشان میدهد که ما متوقفش نمیکنیم، تا این حالتِ صادقانه نتواند بیصدا ناپدید شود.
بازتولیدپذیری
هر عدد اینجا از یک محکزنی کامیتشده میآید که با یک فرمان بازمیگردد، در کنار آزمونها، مجموعههای انطباق میانزبانی و میانپیادهسازی، و ماتریس CI که Python از 3.10 تا 3.14 را با و بدون هسته بومی بهکار میگیرد. روششناسی، JSON خام، و یادداشتهای تصمیم (از جمله ابعادی که هر انتخاب در آنها میبازد) در مخزناند، چون لایهای که هوش مصنوعی را حسابرسیپذیر میکند خود باید حسابرسیپذیر باشد.