~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-socialweb-computer-requester

socialweb.computer market requester and policy modules for atlibs, with its web pages and lexicons

0
0
main
106 lines · 5.4 KB Raw History
// node --test web/webrtc/attest.test.mjs
// javascript/src/attest with secp256k1 from node:crypto (no npm deps): the live RFP vector, and
// signatures OpenSSL verifies. The page injects @noble/curves instead.
import assert from "node:assert/strict";
import { createECDH, createPrivateKey, createPublicKey, randomBytes, sign, verify } from "node:crypto";
import { test } from "node:test";

import { attestHost, attestationCid, didKey } from "../../../atlibs/javascript/src/attest/index.js";

const N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n;
const b64u = (bytes) => Buffer.from(bytes).toString("base64url");
const big = (bytes) => BigInt(`0x${Buffer.from(bytes).toString("hex")}`);
const jwk = (uncompressed, d) => ({ kty: "EC", crv: "secp256k1", x: b64u(uncompressed.subarray(1, 33)), y: b64u(uncompressed.subarray(33)), ...(d && { d: b64u(d) }) });
const uncompress = (publicKey) => createECDH("secp256k1").constructor.convertKey(publicKey, "secp256k1", undefined, undefined, "uncompressed");

// The slice of @noble/curves 2.x secp256k1 that attest uses: compact r||s, low-S, sha256 prehash.
const secp256k1 = {
	utils: { randomSecretKey: () => new Uint8Array(randomBytes(32)) },
	getPublicKey(secretKey, compressed) {
		const ecdh = createECDH("secp256k1");
		ecdh.setPrivateKey(secretKey);
		return new Uint8Array(ecdh.getPublicKey(null, compressed ? "compressed" : "uncompressed"));
	},
	sign(message, secretKey) {
		const key = createPrivateKey({ key: jwk(this.getPublicKey(secretKey, false), secretKey), format: "jwk" });
		const rs = new Uint8Array(sign("sha256", message, { key, dsaEncoding: "ieee-p1363" }));
		const s = big(rs.subarray(32));
		if (s > N / 2n) rs.set(Buffer.from((N - s).toString(16).padStart(64, "0"), "hex"), 32);
		return rs;
	},
};
const verifies = (signature, message, didkey) => {
	const publicKey = Buffer.from(base58decode(didkey.slice("did:key:z".length))).subarray(2);
	const key = createPublicKey({ key: jwk(uncompress(publicKey)), format: "jwk" });
	return verify("sha256", message, { key, dsaEncoding: "ieee-p1363" }, Buffer.from(signature, "base64"));
};
function base58decode(text) {
	let n = 0n;
	for (const c of text) n = n * 58n + BigInt("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".indexOf(c));
	const hex = n.toString(16);
	return Buffer.from(hex.padStart(hex.length + (hex.length % 2), "0"), "hex");
}

// The signed RFP the live bidders accepted (at://did:plc:lpfuqerea3deuoyrn7ojser4/com.publicdomainrelay.temp.market.rfp/3mzof3sr6ez2e).
const RFP_REPO = "did:plc:lpfuqerea3deuoyrn7ojser4";
const RFP = {
	$type: "com.publicdomainrelay.temp.market.rfp",
	domain: "compute",
	payload: {
		cid: "bafyreigh3k4lw4txsk4ojkx3b3x7i32umdi26vmzo2vw3oxyxkfyfckvja",
		uri: "at://did:plc:lpfuqerea3deuoyrn7ojser4/com.publicdomainrelay.temp.compute.vm/3mzof3sah7v2t",
		$type: "com.atproto.repo.strongRef",
	},
	policies: [
		{
			cid: "bafyreigr27gkscq2otmv5xfmyx3t2s32ga63xcwp2amafubjyxfd4oky5y",
			uri: "at://did:plc:lpfuqerea3deuoyrn7ojser4/computer.socialweb.temp.policy.ghalite/3mzof3sjie32i",
			$type: "com.atproto.repo.strongRef",
		},
	],
	createdAt: "2026-11-06T22:02:10.263Z",
	signatures: [
		{
			cid: "bafyreifxbegxhn5nds47mb74segtp75sdtm5iva45l7tphfykkeliax3ca",
			key: "did:key:zQ3shXLEhJWkcH5M1dceCTRkkPajiZ7sAxAbvPMLbtNSLLxaP",
			$type: "network.attested.signature",
			issuer: "did:plc:lpfuqerea3deuoyrn7ojser4",
			signature: { $bytes: "W1NmGCHM1MwpsXEgt2x8N4ZPpwFIunGzzAm5AxaqWoYelO+UH2zp8ZUitHRgv/4itLteOKEePEhvKF4OdLUS6g" },
		},
	],
};

test("the RFP the bidders accepted: same CID, and its signature verifies", async () => {
	const entry = RFP.signatures[0];
	const { bytes, cid } = await attestationCid(RFP, entry, RFP_REPO);
	assert.equal(cid, entry.cid);
	assert.ok(verifies(entry.signature.$bytes, bytes, entry.key));
	assert.notEqual((await attestationCid({ ...RFP, domain: "other" }, entry, RFP_REPO)).cid, entry.cid);
	assert.notEqual((await attestationCid(RFP, entry, "did:plc:other")).cid, entry.cid);
});

test("attestHost: one stored key per DID, output = input + signatures, repository must be the session DID", async () => {
	const store = new Map();
	const ctx = { settings: { get: async (k) => store.get(k), set: async (k, v) => store.set(k, v) } };
	const attest = attestHost(ctx, secp256k1, RFP_REPO);
	const { key } = await attest({ repository: RFP_REPO });
	assert.match(key, /^did:key:zQ3s/);
	assert.equal(key, didKey(secp256k1.getPublicKey(Buffer.from(store.get("attestKeys")[RFP_REPO], "hex"), true)));

	const { signatures: _, ...unsigned } = RFP;
	const out = await attest({ repository: RFP_REPO, record: unsigned });
	assert.equal(out.key, key);
	const { signatures: [entry], ...rest } = out.record;
	assert.deepEqual(rest, unsigned);
	assert.deepEqual(Object.keys(entry).sort(), ["$type", "cid", "issuer", "key", "signature"]);
	assert.equal(entry.issuer, RFP_REPO);
	const { bytes, cid } = await attestationCid(out.record, entry, RFP_REPO);
	assert.equal(entry.cid, cid);
	assert.ok(verifies(entry.signature.$bytes, bytes, key));
	assert.equal((await attest({ repository: RFP_REPO, record: out.record })).record.signatures.length, 2);

	await assert.rejects(attest({ repository: "did:plc:someoneelse", record: unsigned }), /session DID/);
	await assert.rejects(attestHost(ctx, secp256k1, undefined)({ repository: undefined }), /session DID/);
	await assert.rejects(attest({ repository: RFP_REPO, record: [] }), /object/);
	assert.notEqual((await attestHost(ctx, secp256k1, "did:plc:two")({ repository: "did:plc:two" })).key, key);
});