Katso oppituntivideo: AI-agenttien suojaaminen kryptografisilla kuiteilla
(Oppituntivideo ja pikkukuva lisätään Microsoftin sisältötiimin toimesta yhdistämisen jälkeen, vastaamaan oppituntien 14 / 15 kaavaa.)
Tässä oppitunnissa käsitellään:
Oppitunnin suorittamisen jälkeen osaat:
Kuvittele, että olet käyttöönotanut AI-agentin Contoso Travelille. Agentti lukee asiakkaan pyyntöjä, kutsuu lentojen APIa vaihtoehtojen hakemiseksi ja varaa paikkoja asiakkaan puolesta. Viimeisellä neljänneksellä agentti käsitteli 50 000 varausta.
Nyt paikalle saapuu tarkastaja. Hän kysyy yksinkertaisen kysymyksen: “Näytä minulle, mitä agenttisi teki.”
Luovutat lokitiedostosi. Tarkastaja katsoo niitä ja kysyy vaikeamman kysymyksen: “Miten tiedän, ettei näitä lokeja ole muokattu?”
Tämä on auditointijälki-ongelma. Useimmat agenttien käyttöönotot nykyään luottavat:
Kukaan näistä ei voi vastata tarkastajan kysymykseen ilman, että tarkastaja luottaa johonkin (sinuun, pilvipalveluntarjoajaasi, tietokantatoimittajaasi). Sisäisessä käytössä tämä luottamus usein kelpaa. Säädellyissä työkuormissa (rahoitus, terveydenhuolto, EU:n tekoälydirektiivin alaiset) ei.
Kryptografiset kuitit ratkaisevat tämän tekemällä jokaisen agentin toiminnon itsenäisesti varmennettavaksi. Tarkastajan ei tarvitse luottaa sinuun. Hän tarvitsee vain julkisen avaimesi ja kuitin itsessään.
Kuitti on JSON-objekti, joka tallentaa, mitä agentti teki, ja on allekirjoitettu digitaalisella allekirjoituksella.
flowchart LR
A[Agentti kutsuu työkalua] --> B[Rakennetaan kuittipayload]
B --> C[Normeerataan JSON RFC 8785]
C --> D[SHA-256 tiiviste]
D --> E[Ed25519 allekirjoitus]
E --> F[Kuitti allekirjoituksella]
F --> G[Tarkastaja tarkistaa offline-tilassa]
G --> H{Onko allekirjoitus voimassa?}
H -- yes --> I[Muokkaussuojattu todiste]
H -- no --> J[Kuitti hylätty]
Minimaalinen kuitti näyttää tältä:
{
"type": "agent.tool_call.v1",
"agent_id": "contoso-travel-bot",
"tool_name": "lookup_flights",
"tool_args_hash": "sha256:a3f9c1...",
"result_hash": "sha256:7b2e1d...",
"policy_id": "contoso-travel-policy-v3",
"timestamp": "2026-04-25T14:30:00Z",
"sequence": 47,
"previous_receipt_hash": "sha256:9d4e6a...",
"signature": {
"alg": "EdDSA",
"sig": "c5af83...",
"public_key": "8f3b2c..."
}
}
Kolme ominaisuutta tekee työn:
Allekirjoitus. Kuitti on allekirjoitettu agentin portin toimesta Ed25519-yksityisavaimella. Kuka tahansa, jolla on vastaava julkinen avain, voi tarkistaa allekirjoituksen offline-tilassa. Kentän muuttaminen mitätöi allekirjoituksen.
Kanoninen koodaus. Ennen allekirjoittamista kuitti sarjallistetaan JSON Kanonisointisääntöjen (JCS, RFC 8785) mukaisesti. Tämä varmistaa, että kaksi eri toteutusta, jotka tuottavat saman loogisen kuitin, tuottavat tavu-identtisen ulostulon. Ilman kanonisointia erilaiset JSON-sarjallistimet tuottaisivat eri allekirjoituksia samalle sisällölle.
Hash-ketjuuntaminen. previous_receipt_hash-kenttä linkittää jokaisen kuitin sitä edeltävään. Yhden kuitin poistaminen tai uudelleenjärjestäminen rikkoo kaikki sitä seuraavat kuitit. Manipulointi tulee näkyväksi ketjutasolla, vaikka yksittäiset allekirjoitukset pettäisivät.
Nämä ominaisuudet yhdessä tarjoavat kolme takuuta:
Et tarvitse erillistä kirjastoa kuitin tuottamiseen. Kryptografiset perusrakenteet ovat laajalti saatavilla ja logiikka on muutama kymmenen riviä Pythonia.
Käytännön harjoitukset tiedostossa code_samples/18-signed-receipts.ipynb käyvät koko prosessin läpi. Yhteenvetona:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanoninen JSON
def b64url_nopad(data: bytes) -> str:
return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")
def sha256_canonical(obj) -> str:
"""SHA-256 of a Python object's JCS-canonical JSON form."""
return f"sha256:{hashlib.sha256(canonicalize(obj)).hexdigest()}"
# Luo tai lataa allekirjoitusavain (tuotannossa tallenna avainholviin)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Rakenna kuittauksen sisältö (ei vielä allekirjoitusta)
tool_args = {"origin": "SYD", "destination": "LAX"}
tool_result = [{"flight": "QF11", "price": 1850, "stops": 0}]
payload = {
"type": "agent.tool_call.v1",
"agent_id": "contoso-travel-bot",
"tool_name": "lookup_flights",
"tool_args_hash": sha256_canonical(tool_args),
"result_hash": sha256_canonical(tool_result),
"policy_id": "contoso-travel-policy-v3",
"timestamp": "2026-04-25T14:30:00Z",
"sequence": 0,
"previous_receipt_hash": None,
}
# Kanonisoi, hajauta, allekirjoita.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Liitä rakenteellinen allekirjoitusobjekti.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
Tämä on koko allekirjoitusputki. Tehtävät muistikirjassa käyvät jokaisen vaiheen yksityiskohtaisesti.
Varmistus on käänteinen operaatio:
import base64
import hashlib
from nacl import signing
from nacl.exceptions import BadSignatureError
from jcs import canonicalize
def b64url_decode(s: str) -> bytes:
padding = "=" * ((4 - len(s) % 4) % 4)
return base64.urlsafe_b64decode(s + padding)
def verify_receipt(receipt: dict) -> bool:
# Allekirjoitus on jäsennelty objekti: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Rakenna uudelleen kuorma, joka todellisuudessa allekirjoitettiin (kaikki paitsi allekirjoitus).
payload = {k: v for k, v in receipt.items() if k != "signature"}
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
try:
verify_key = signing.VerifyKey(b64url_decode(sig_obj["public_key"]))
verify_key.verify(message_hash, b64url_decode(sig_obj["sig"]))
return True
except BadSignatureError:
return False
Tämä funktio ottaa kuitin ja palauttaa True, jos allekirjoitus on validi, muuten False. Ei verkkokutsuja, ei palveluriippuvuuksia, ei luottamusta kolmanteen osapuoleen.
Manipuloinnin havaitsemisen näet tekemällä:
tool_args_hash-kentässä.Tämä on käytännön osoitus siitä, että kuitit ovat väärinkäytöksiä estäviä: mikä tahansa muutos, miten pieni tahansa, rikkoo allekirjoituksen.
Yksi allekirjoitettu kuitti suojaa yhtä toimintoa. Kuituketju suojaa toimintojen sarjaa.
flowchart LR
R0[Vastaanotto 0<br/>alkuperäinen] --> R1[Vastaanotto 1]
R1 --> R2[Vastaanotto 2]
R2 --> R3[Vastaanotto 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Jokainen kuitti tallentaa edellisen kuitin hashin. Jos hyökkääjä haluaa poistaa kuitin 2 huomaamattomasti, hänen täytyisi joko:
previous_receipt_hash-kenttää (rikkoutuu kuitin 3 allekirjoitus), TAIJos yksityisavain on laitteistoturvakaapissa ja julkaiset julkisen avaimen jokaisen kuitin yhteydessä, kumpikaan hyökkäys ei ole toteutettavissa huomaamatta.
Muistikirjassa käydään läpi:
previous_receipt_hash-kentän vastaavuuden varmistaminen edeltävän kuitin todelliseen hash-arvoon.Tällä tavalla tuot auditointijäljen, jonka ulkopuolinen tarkastaja voi varmentaa ilman luottamusta sinuun.
Tämä on tämän oppitunnin tärkein osio. Kuitit ovat voimakkaita, mutta niiden voima on rajattu.
Kuitit todistavat kolme asiaa:
Kuitit EIVÄT todista:
policy_id-kentässä mainittu politiikka todella arvioitiin tai että se olisi sallinut toiminnon. Kuitti tallentaa väitteen, ei toimeenpanoa.Tämä raja on tärkeä kahdesta syystä:
Yleinen virhe on olettaa, että “meillä on kuitit” tarkoittaa “meitä valvotaan.” Ei tarkoita. Kuitit ovat perusta. Hallinto on järjestelmä, jonka rakennat niiden päälle.
Tämän oppitunnin Python-koodi on tarkoituksella minimaalista, jotta voit lukea jokaisen rivin ja ymmärtää tarkasti, mitä tapahtuu. Tuotantokäytössä sinulla on kaksi vaihtoehtoa:
Rakenna suoraan kryptografisten primitiivien päälle. Yllä näkemäsi noin 50 riviä riittävät moniin käyttötapauksiin. PyNaCl (Ed25519) ja jcs-paketti (kanoninen JSON) ovat hyvin ylläpidettyjä ja auditoituja kirjastoja.
Käytä tuotantolaatuista kuittikirjastoa. Useat avoimen lähdekoodin projektit toteuttavat samaa kaavaa lisäominaisuuksilla (avaimien kierto, erävarmennus, JWK Set -jakelu, integraatio politiikka-moottoreihin):
draft-farley-acta-signed-receipts), joka on standardointiprosessissa.protect-mcp (npm) ja @veritasacta/verify (npm) tarjoavat Node-pohjaiset toteutukset kuittien allekirjoitukseen ja offline-varmennukseen, tarkoitettuja minkä tahansa MCP-palvelimen ympärille tamper-evident audit trailin rakentamiseen.Päätös oman toteutuksen ja kirjaston käytön välillä vastaa päätöstä kirjoittaa oma JWT-kirjasto tai käyttää testattua: molemmat ovat järkeviä; kirjasto säästää aikaa ja vähentää auditointialuetta; oma toteutus pakottaa ymmärtämään jokaisen primitiivin. Tämä oppitunti opettaa oman toteutuksen mallin, jotta sinulla on perusta kumpaankin.
Testaa ymmärryksesi ennen siirtymistä harjoitustehtävään.
1. Kuitti allekirjoitetaan agentin yksityisellä Ed25519-avaimella. Tarkastajalla on vain julkinen avain. Voiko tarkastaja varmistaa kuitin offline?
2. Hyökkääjä muuttaa kuitin policy_id-kenttää väittäen, että sitä säätelee sallivampi politiikka. Allekirjoitus oli alkuperäisen payloadin yli. Mitä tapahtuu varmennuksen aikana?
3. Miksi kuitti sisältää tool_args_hash- ja result_hash-kentät sen sijaan, että se sisältäisi raakadatan työkalun argumenteista ja tuloksista?
4. previous_receipt_hash linkittää jokaisen kuitin edeltäjäänsä. Jos hyökkääjä poistaa hiljaisesti yhden kuitin ketjusta keskeltä, mikä menee mitättömäksi?
5. Kuitti varmistetaan onnistuneesti. Todistaako se, että agentin toiminta oli oikea, pätevä tai politiikan mukainen?
Avaa tiedosto code_samples/18-signed-receipts.ipynb ja suorita kaikki neljä osiota:
Lisähaaste 1: laajenna kuitin skeemaa yhdellä omavalintaisella kentällä (esimerkiksi pyyntö-ID jäljitystä varten), päivitä kanoninen allekirjoituslogiikka ottamaan se mukaan ja varmistu, että kuitti kulkee varmennusprosessin läpi onnistuneesti. Muokkaa sitten kenttää allekirjoittamisen jälkeen ja varmista, että varmennus epäonnistuu. Tämä pakottaa ymmärtämään, miten jokainen tavu kanonisessa koodauksessa vaikuttaa allekirjoitukseen. Haastava lisätehtävä 2: SHA-256-tiivistä kaksi kuittiasi yhteen (yhdistä niiden kanoniset tavut määrätyssä järjestyksessä) ja upota syntynyt tiiviste kolmannen kuitin uudeksi kentäksi ennen sen allekirjoittamista. Varmista, että kaikki kolme kuittia voivat edelleen kulkea edestakaisin. Olet juuri rakentanut yksivaiheisen sisällyttämistodisteen: kuka tahansa, joka pitää hallussaan kolmatta kuittia, voi todistaa, että kaksi ensimmäistä kuittia olivat olemassa sen allekirjoitushetkellä paljastamatta niiden sisältöä. Tämä on malli, jota valikoiva-paljastuskuittaukset käyttävät laajassa mittakaavassa (Merkle-sitoumukset, RFC 6962).
Kryptografiset kuitit antavat tekoälyagentteille tarkastusjäljen, joka on:
Ne eivät korvaa syötteen validointia, politiikan toimeenpanoa tai identiteettijärjestelmää. Ne ovat niiden kerrosten perusta. Kun otat agentteja käyttöön säännellyissä työkuormissa, moniorganisaatiotyönkuluissa tai missä tahansa tilanteessa, jossa tuleva tarkastaja ei oletuksena luota sinuun, kuitit ovat tapa tehdä tarkastusjäljestä rehellinen.
Tärkein opetus: kuitit todistavat kuka sanoi mitä ja milloin. Ne eivät todista, että sanottu oli totta tai oikeaa. Säilytä tämä ero tarkasti. Se on ero rehellisen alkuperäjärjestelmän ja harhaanjohtavan välillä.
Kun olet valmis siirtymään tästä oppitunnista ja käyttämään kuittien allekirjoittamia agenteja todellisessa ympäristössä:
https://your-org.example.com/.well-known/agent-keys.json.Liity Microsoft Foundry Discordiin tavata muita oppijoita, osallistua aukioloihin ja saada vastauksia AI-agenttikysymyksiisi.
Tämä oppitunti käsittelee yksittäisen kuitin allekirjoitusta ja hajautetun ketjun sekvenssejä. Samat primitiivit muodostavat useita edistyneempiä malleja, joita voit kohdata hallintamallisi kehittyessä:
authorization_*) ja jälkisuoritusvaiheen (result_*) puoliksi riippumattomilla allekirjoituksilla, hyödyllistä kun valtuutuspäätöksen ja havaittujen tulosten tuottavat eri toimijat tai eri ajat. Tämä yhdistyy opetusoppitunnin kuittiformaattiin lisäkerroksena.result_hash-kenttään. Käytännön tosiasiat ovat usein monipuolisempia kuin yhden työkalukutsun tulos: päätösperustelut (mallin ennuste, harkitut vaihtoehdot, todisteet ja niiden kattavuus, riskiasema, vastuuketju, portin lopputulos) voivat kaikki asua tässä sisältöobjektissa, jota yksi kuitti sulkee. Näin säilytetään kuittimuoto yksinkertaisena samalla, kun tietomallit voivat kehittyä toimialakohtaisesti.signature.alg-kenttä voi sisältää ML-DSA-65 (NISTin jälkikvantti allekirjoitusstandardi) siirtymää varten. Suunnittele siirtymävaihe, jossa kuitit allekirjoitetaan kahdesti.Tietokoneen käyttöagenttien rakentaminen (CUA)
(Määritellään opetussuunnitelman ylläpitäjien toimesta)
Vastuuvapauslauseke: Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua Co-op Translator. Vaikka pyrimme tarkkuuteen, otathan huomioon, että automaattiset käännökset saattavat sisältää virheitä tai epätarkkuuksia. Alkuperäinen asiakirja sen alkuperäiskielellä on virallinen lähde. Tärkeissä asioissa suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa tämän käännöksen käytöstä aiheutuvista väärinymmärryksistä tai tulkinnoista.