@t2000/sdk 5.19.0 → 5.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +90 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +90 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -2113,6 +2113,72 @@ function verifyReceiptSignature(receipt, signingKeyHex) {
|
|
|
2113
2113
|
return false;
|
|
2114
2114
|
}
|
|
2115
2115
|
}
|
|
2116
|
+
async function verifyTdxQuote(base, model, receiptWorkloadId) {
|
|
2117
|
+
let nonce;
|
|
2118
|
+
try {
|
|
2119
|
+
nonce = utils$1.bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
2120
|
+
} catch {
|
|
2121
|
+
return { status: "skip", detail: "no secure RNG available", forged: false };
|
|
2122
|
+
}
|
|
2123
|
+
let report;
|
|
2124
|
+
try {
|
|
2125
|
+
const res = await fetch(
|
|
2126
|
+
`${base}/aci/attestation?model=${encodeURIComponent(model)}&nonce=${nonce}`
|
|
2127
|
+
);
|
|
2128
|
+
if (res.ok) {
|
|
2129
|
+
report = (await res.json()).report;
|
|
2130
|
+
}
|
|
2131
|
+
} catch {
|
|
2132
|
+
}
|
|
2133
|
+
const quoteHex = report?.attestation?.evidence?.quote;
|
|
2134
|
+
if (!quoteHex) {
|
|
2135
|
+
return {
|
|
2136
|
+
status: "skip",
|
|
2137
|
+
detail: "attestation report (with quote) unavailable \u2014 pass --model?",
|
|
2138
|
+
forged: false
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
try {
|
|
2142
|
+
const dcap = await import('@phala/dcap-qvl');
|
|
2143
|
+
const getCollateralAndVerify = dcap.getCollateralAndVerify ?? dcap.default?.getCollateralAndVerify;
|
|
2144
|
+
if (typeof getCollateralAndVerify !== "function") {
|
|
2145
|
+
return {
|
|
2146
|
+
status: "fail",
|
|
2147
|
+
forged: false,
|
|
2148
|
+
detail: "DCAP verifier unavailable in this build"
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
const quoteBytes = utils$1.hexToBytes(quoteHex.replace(/^0x/, ""));
|
|
2152
|
+
const vr = await getCollateralAndVerify(quoteBytes);
|
|
2153
|
+
const td = vr.report.asTd10() ?? vr.report.asTd15()?.base ?? null;
|
|
2154
|
+
const reportData = td?.reportData;
|
|
2155
|
+
const signingAddr = report?.signing_address?.replace(/^0x/, "").toLowerCase();
|
|
2156
|
+
const addrBound = Boolean(
|
|
2157
|
+
reportData && signingAddr && utils$1.bytesToHex(reportData.slice(0, 20)) === signingAddr
|
|
2158
|
+
);
|
|
2159
|
+
const workloadMatch = report?.workload_id === receiptWorkloadId;
|
|
2160
|
+
const tcb = vr.status;
|
|
2161
|
+
const tcbBad = tcb === "Revoked" || tcb === "Unknown";
|
|
2162
|
+
const forged = !(addrBound && workloadMatch) || tcbBad;
|
|
2163
|
+
let detail;
|
|
2164
|
+
if (forged && tcbBad) {
|
|
2165
|
+
detail = `genuine TDX but TCB ${tcb}`;
|
|
2166
|
+
} else if (!addrBound) {
|
|
2167
|
+
detail = "report_data does NOT commit the report's signing address";
|
|
2168
|
+
} else if (!workloadMatch) {
|
|
2169
|
+
detail = "quote workload_id does not match the receipt's";
|
|
2170
|
+
} else {
|
|
2171
|
+
detail = `genuine Intel TDX (verified vs Intel collateral), TCB ${tcb}; report_data commits the attested signing address`;
|
|
2172
|
+
}
|
|
2173
|
+
return { status: forged ? "fail" : "pass", forged, tcbStatus: tcb, detail };
|
|
2174
|
+
} catch (e) {
|
|
2175
|
+
return {
|
|
2176
|
+
status: "fail",
|
|
2177
|
+
forged: false,
|
|
2178
|
+
detail: `could not verify the quote: ${e instanceof Error ? e.message : "error"}`
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2116
2182
|
async function verifyReceipt(receiptId, opts = {}) {
|
|
2117
2183
|
const base = opts.apiBase ?? DEFAULT_API_BASE;
|
|
2118
2184
|
const network = opts.network ?? "mainnet";
|
|
@@ -2207,7 +2273,6 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2207
2273
|
});
|
|
2208
2274
|
}
|
|
2209
2275
|
}
|
|
2210
|
-
let signatureForged = false;
|
|
2211
2276
|
let sigStatus = "skip";
|
|
2212
2277
|
let sigDetail = "no signature on receipt";
|
|
2213
2278
|
if (receipt.signature?.value) {
|
|
@@ -2224,7 +2289,6 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2224
2289
|
} else {
|
|
2225
2290
|
const ok = verifyReceiptSignature(receipt, att.signingKey);
|
|
2226
2291
|
sigStatus = ok ? "pass" : "fail";
|
|
2227
|
-
signatureForged = !ok;
|
|
2228
2292
|
sigDetail = ok ? `signed by the attested receipt key (${receipt.signature.key_id ?? "key"})` : "signature does NOT recover the attested receipt key \u2014 forged/altered";
|
|
2229
2293
|
}
|
|
2230
2294
|
} catch {
|
|
@@ -2237,9 +2301,32 @@ async function verifyReceipt(receiptId, opts = {}) {
|
|
|
2237
2301
|
detail: sigDetail,
|
|
2238
2302
|
trust: sigStatus === "skip" ? "roadmap" : "trustless"
|
|
2239
2303
|
});
|
|
2304
|
+
if (opts.skipQuote) {
|
|
2305
|
+
checks.push({
|
|
2306
|
+
name: "TDX quote (DCAP)",
|
|
2307
|
+
status: "skip",
|
|
2308
|
+
detail: "skipped (--quick)",
|
|
2309
|
+
trust: "trustless"
|
|
2310
|
+
});
|
|
2311
|
+
} else {
|
|
2312
|
+
const q = await verifyTdxQuote(
|
|
2313
|
+
base,
|
|
2314
|
+
opts.model ?? "phala/glm-5.2",
|
|
2315
|
+
workloadId ?? ""
|
|
2316
|
+
);
|
|
2317
|
+
checks.push({
|
|
2318
|
+
name: "TDX quote (DCAP)",
|
|
2319
|
+
status: q.status,
|
|
2320
|
+
detail: q.detail,
|
|
2321
|
+
trust: "trustless"
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
const trustlessFailed = checks.some(
|
|
2325
|
+
(c) => c.trust === "trustless" && c.status === "fail"
|
|
2326
|
+
);
|
|
2240
2327
|
return {
|
|
2241
2328
|
receiptId,
|
|
2242
|
-
verified: Boolean(wireHash && workloadId) &&
|
|
2329
|
+
verified: Boolean(wireHash && workloadId) && !trustlessFailed,
|
|
2243
2330
|
anchorVerified,
|
|
2244
2331
|
checks,
|
|
2245
2332
|
wireHash,
|