# CBIO agent login (`https://c.bio/llms.txt`) CBIO is a decentralized encrypted identity and authentication layer for autonomous agents. Use this file to obtain a CBIO `passport` and authenticate to the target site API. ## Goal Get a valid CBIO `passport` JWT and send the **target site API request** with: `Authorization: Bearer ` ## Inputs you need before starting | Name | Where it comes from | Notes | | --- | --- | --- | | `aud` | The target site | Must be an `http`/`https` origin only (no path/query/fragment). Example: `https://shop.example.com` | | `root_public_key` | Your local Ed25519 keypair | SPKI DER, base64url | | `privateKeyBase64url` | Your local Ed25519 keypair | PKCS#8 DER, base64url | | `root_agent_id` | Derived locally | `deriveRootAgentId(root_public_key)` | ## Offline prerequisites (generate keys, no network) If you already have `root_public_key` and `privateKeyBase64url`, skip this section. ### Generate Ed25519 keypair (offline) and export formats Run this locally (no network): ```node const crypto = require('node:crypto'); const ROOT_AGENT_ID_PREFIX = 'agt_'; function deriveRootAgentId(rootPublicKey) { const rawKey = Buffer.from(rootPublicKey, 'base64url'); const hash = crypto.createHash('sha256').update(rawKey).digest('base64url'); return ROOT_AGENT_ID_PREFIX + hash; } const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519', { publicKeyEncoding: { type: 'spki', format: 'der' }, privateKeyEncoding: { type: 'pkcs8', format: 'der' } }); const root_public_key = publicKey.toString('base64url'); const privateKeyBase64url = privateKey.toString('base64url'); const root_agent_id = deriveRootAgentId(root_public_key); console.log(JSON.stringify({ root_public_key, privateKeyBase64url, root_agent_id }, null, 2)); ``` ### Derivation formula (what `deriveRootAgentId` means) `root_agent_id = 'agt_' + base64url( sha256( base64urlDecode(root_public_key) ) )` ## Do this now (default: offline key ops) 1. Get `aud` from the target site. 2. Derive `root_agent_id` locally from `root_public_key`. 3. Request nonce: - `POST https://actions.c.bio/identity/v1/challenge` - Body: `{"root_agent_id":"agt_..."}` 4. Read `nonce` from response. 5. Sign `nonce` locally: - `signature = signPayload(privateKeyBase64url, nonce)` If you want a local script (offline): ```node const crypto = require('node:crypto'); const privateKeyBase64url = 'PASTE_PRIVATEKEYBASE64URL_HERE'; const nonce = 'PASTE_NONCE_HERE'; const privKeyDer = Buffer.from(privateKeyBase64url, 'base64url'); const dataBuffer = Buffer.from(nonce); const signature = crypto.sign(null, dataBuffer, { key: privKeyDer, format: 'der', type: 'pkcs8' }).toString('base64url'); console.log(JSON.stringify({ signature }, null, 2)); ``` 6. Verify and get passport: - `POST https://actions.c.bio/identity/v1/verify` - Body must include: `root_agent_id`, `nonce`, `signature`, `aud`, `root_public_key` (first time for this agent) - Read `passport` from response. 7. Send the target site API request with `Authorization: Bearer `. ## If it fails - Missing `aud`: stop and request `aud` from the target site. - Verify fails: check `aud` exact match, `nonce` freshness, and signature/key format. - Still 401 at target site: re-fetch a new `passport` and send the request once more. ## Optional SDK path SDK is optional. If used, it must perform the same flow above (`challenge -> sign -> verify`) and return `passport`. ## What the target site verifies The target site verifies JWT with: - JWKS: `https://actions.c.bio/.well-known/jwks.json` - `iss === "https://c.bio"` - `aud` equals the `aud` value that site provided