Some checks failed
JavaScript SDK Tests / test-js-sdk (push) Successful in 16s
package-tests / test-python-packages (map[name:aitbc-agent-sdk path:packages/py/aitbc-agent-sdk python_version:3.13]) (push) Failing after 9s
package-tests / test-python-packages (map[name:aitbc-core path:packages/py/aitbc-core python_version:3.13]) (push) Failing after 9s
package-tests / test-python-packages (map[name:aitbc-crypto path:packages/py/aitbc-crypto python_version:3.13]) (push) Successful in 8s
package-tests / test-python-packages (map[name:aitbc-sdk path:packages/py/aitbc-sdk python_version:3.13]) (push) Successful in 13s
package-tests / test-javascript-packages (map[name:aitbc-sdk node_version:24 path:packages/js/aitbc-sdk]) (push) Successful in 10s
package-tests / cross-language-compatibility (push) Has been skipped
package-tests / package-integration-tests (push) Has been skipped
security-scanning / audit (push) Successful in 1m22s
integration-tests / test-service-integration (push) Successful in 3m22s
80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { generateKeyPairSync, sign } from "crypto";
|
|
import { ReceiptService } from "./receipts";
|
|
import type { ReceiptSummary } from "./types";
|
|
|
|
class ThrowingClient {
|
|
async request() {
|
|
throw new Error("offline");
|
|
}
|
|
}
|
|
|
|
describe("ReceiptService signature verification", () => {
|
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
const publicKeyPem = publicKey
|
|
.export({ type: "spki", format: "pem" })
|
|
.toString();
|
|
|
|
const baseReceipt: ReceiptSummary = {
|
|
receiptId: "r1",
|
|
jobId: "job-123",
|
|
miner: "miner-1",
|
|
coordinator: "coord-1",
|
|
issuedAt: new Date().toISOString(),
|
|
status: "completed",
|
|
payload: {
|
|
job_id: "job-123",
|
|
provider: "miner-1",
|
|
client: "client-1",
|
|
},
|
|
};
|
|
|
|
const signPayload = (payload: Record<string, unknown>): string => {
|
|
const message = Buffer.from(JSON.stringify(payload));
|
|
return sign(null, message, privateKey).toString("base64");
|
|
};
|
|
|
|
it("validates with provided PEM keys", async () => {
|
|
const sig = signPayload(baseReceipt.payload!);
|
|
const receipt: ReceiptSummary = {
|
|
...baseReceipt,
|
|
payload: {
|
|
...baseReceipt.payload,
|
|
minerSignature: sig,
|
|
coordinatorSignature: sig,
|
|
},
|
|
};
|
|
|
|
const svc = new ReceiptService({
|
|
client: new ThrowingClient() as any,
|
|
minerPublicKeyPem: publicKeyPem,
|
|
coordinatorPublicKeyPem: publicKeyPem,
|
|
signatureAlgorithm: "ed25519",
|
|
});
|
|
|
|
const result = await svc.validateReceipt(receipt);
|
|
expect(result.valid).toBe(true);
|
|
});
|
|
|
|
it("fails with bad signature", async () => {
|
|
const receipt: ReceiptSummary = {
|
|
...baseReceipt,
|
|
payload: {
|
|
...baseReceipt.payload,
|
|
minerSignature: "bad",
|
|
coordinatorSignature: "bad",
|
|
},
|
|
};
|
|
|
|
const svc = new ReceiptService({
|
|
client: new ThrowingClient() as any,
|
|
minerPublicKeyPem: publicKeyPem,
|
|
coordinatorPublicKeyPem: publicKeyPem,
|
|
signatureAlgorithm: "ed25519",
|
|
});
|
|
|
|
const result = await svc.validateReceipt(receipt);
|
|
expect(result.valid).toBe(false);
|
|
});
|
|
});
|