Public
Script
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

secure signatures with vals

setup

you'll need to make 2 new vals:

  1. generate a keypair (keep this val private)
    let vsExportedKeys = @easrng.generateKeys();
  2. publish your public key (make this val public)
    const vsPublicKey = () => @me.exportedKeys.publicKey;

usage

sign

call @easrng.valSign to get a signature.

const signature = await @easrng.valSign({ keys: @me.vsExportedKeys, data: {hello: "world"}})

the result will look something like this:

@easrng.htVgaVWWtvnz5AK0DnDaNON5gar5qJeaorfsTCiIr7ua_-D4HPmFrIrPMfwmCaMvI0CxKlYCUe9XTGm7r5s5C3siZGF0YSI6eyJoZWxsbyI6IndvcmxkIn0sInVzZXIiOiJlYXNybmciLCJleHByIjpudWxsfQ

you can also set an expiration date:

const signature = await @easrng.valSign({ keys: @me.vsExportedKeys, data: "this expires in 1 second", expireIn: 1000 })

verify

call @easrng.valSignVerify to verify a signature

const { data, handle, expiresAt } = await @easrng.valSignVerify(signature)

with the example signature from earlier, data would be {hello: "world"}, handle would be easrng, and expiresAt would be null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { whoami } from "https://esm.town/v/easrng/whoami";
import { Buffer } from "node:buffer";
export async function valSign({ keys, data, expireIn }: {
keys: {
publicKey: string;
secretKey: string;
};
data: any;
expireIn?: number;
}) {
const topUser = whoami().at(-1).slice(1).split(".")[0];
const verifyPublicKey = await __utils__.api(topUser + ".vsPublicKey");
if (verifyPublicKey !== keys.publicKey)
throw new Error("keypair doesn't match @" + topUser + ".vsPublicKey()");
const { default: nacl } = await import("npm:tweetnacl@1.0.3");
const keyPair = {
publicKey: Buffer.from(keys.publicKey, "base64"),
secretKey: Buffer.from(keys.secretKey, "base64"),
};
const message = new TextEncoder().encode(JSON.stringify({
data,
user: topUser,
expr: expireIn ? Date.now() + expireIn : null,
}));
return "@" + topUser + "."
+ Buffer.from(nacl.sign(message, keyPair.secretKey)).toString("base64url");
}
October 23, 2023