Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions examples/arbitrary_batched.example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) 2025 Cloudflare, Inc.
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

/* eslint-disable security/detect-object-injection */

import { TokenRequest } from '../src/arbitrary_batched_token.js';
import { type Token, type TokenChallenge, arbitraryBatched, publicVerif } from '../src/index.js';
type BlindRSAMode = publicVerif.BlindRSAMode;
const { Client, Issuer } = arbitraryBatched;

async function setupPublicVerif(mode: BlindRSAMode) {
// [ Issuer ] creates a key pair.
const keys = await publicVerif.Issuer.generateKey(mode, {
modulusLength: 2048,
publicExponent: Uint8Array.from([1, 0, 1]),
});
const issuer = new publicVerif.Issuer(mode, 'issuer.com', keys.privateKey, keys.publicKey);
const pkIssuer = await publicVerif.getPublicKeyBytes(issuer.publicKey);

// [ Client ] creates a state.
const client = new publicVerif.Client(mode);

// [ Origin ] creates a state.
const origin = new publicVerif.Origin(mode, ['origin.example.com', 'origin2.example.com']);

return { issuer, client, origin, pkIssuer };
}
async function setup() {
const s1 = await setupPublicVerif(publicVerif.BlindRSAMode.PSS);
const s2 = await setupPublicVerif(publicVerif.BlindRSAMode.PSSZero);

return {
issuers: [s1.issuer, s2.issuer],
clients: [s1.client, s2.client],
origins: [s1.origin, s2.origin],
pkIssuers: [s1.pkIssuer, s2.pkIssuer],
};
}

async function rsaVariant(): Promise<void> {
// Protocol Setup
//
// [ Everybody ] agree to use Public Verifiable Tokens.
const { issuers, clients, origins, pkIssuers } = await setup();
const issuer = new Issuer(issuers[0], issuers[1]);

// [ Client ] creates a state.
const client = new Client();

// Online Protocol
//
// +--------+ +--------+ +----------+ +--------+
// | Origin | | Client | | Attester | | Issuer |
// +---+----+ +---+----+ +----+-----+ +---+----+
// | | | |
// |<----- Request ------+ | |
const tokChls = new Array<TokenChallenge>(origins.length);
let i = 0;
for (const currentIssuer of issuer) {
const redemptionContext = crypto.getRandomValues(new Uint8Array(32));
tokChls[i] = origins[i].createTokenChallenge(currentIssuer.name, redemptionContext);
i += 1;
}
// +-- TokenChallenge -->| | |
// | |<== Attestation ==>| |
// | | | |
const tokReqs = new Array<TokenRequest>(tokChls.length);
for (let i = 0; i < tokChls.length; i += 1) {
const tokReq = await clients[i].createTokenRequest(tokChls[i], pkIssuers[i]);
tokReqs[i] = new TokenRequest(tokReq);
}
const tokReq = client.createTokenRequest(tokReqs);
// | +--------- TokenRequest ------->|
// | | | |
const tokRes = await issuer.issue(tokReq);
// | |<-------- TokenResponse -------+
// | | | |
i = 0;
const tokens = new Array<Token | undefined>(tokChls.length);
for (const res of tokRes) {
if (res.tokenResponse === null) {
continue;
}
const r = publicVerif.TokenResponse.deserialize(res.tokenResponse);
tokens[i] = await clients[i].finalize(r);

i += 1;
}
// |<-- Request+Token ---+ | |
// | | | |
let isValid = true;
for (let i = 0; i < tokens.length; i += 1) {
const token = tokens[i];
isValid &&= token !== undefined && (await origins[i].verify(token, issuers[i].publicKey));
}

console.log('Arbitrary batched tokens');
console.log(` Valid token: ${isValid}`);
}

export async function arbitraryBatchedTokens() {
await rsaVariant();
}
2 changes: 2 additions & 0 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { webcrypto } from 'node:crypto';

import { arbitraryBatchedTokens } from './arbitrary_batched.example.js';
import { publicVerifiableTokens } from './pub_verif.example.js';
import { publicVerifiableWithMetadataTokens } from './pub_verif_metadata.example.js';
import { privateVerifiableTokens } from './priv_verif.example.js';
Expand All @@ -12,6 +13,7 @@ if (typeof crypto === 'undefined') {
}

async function examples() {
await arbitraryBatchedTokens();
await privateVerifiableTokens();
await publicVerifiableTokens();
await publicVerifiableWithMetadataTokens();
Expand Down
15 changes: 7 additions & 8 deletions examples/priv_verif.example.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// Copyright (c) 2023 Cloudflare, Inc.
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

import { TOKEN_TYPES, TokenChallenge, privateVerif } from '../src/index.js';
const { Client, Issuer, keyGen } = privateVerif;
import { TOKEN_TYPES, privateVerif } from '../src/index.js';
const { Client, Issuer, Origin, keyGen } = privateVerif;

export async function privateVerifiableTokens(): Promise<void> {
// Protocol Setup
//
// [ Everybody ] agree to use Private-Verifiable Tokens.
const tokenType = TOKEN_TYPES.VOPRF.value;

// [ Issuer ] creates a key pair.
const keys = await keyGen();
Expand All @@ -18,6 +15,9 @@ export async function privateVerifiableTokens(): Promise<void> {
// [ Client ] creates a state.
const client = new Client();

// [ Origin ] creates a state.
const origin = new Origin(['origin.example.com', 'origin2.example.com']);

// Online Protocol
//
// +--------+ +--------+ +----------+ +--------+
Expand All @@ -26,8 +26,7 @@ export async function privateVerifiableTokens(): Promise<void> {
// | | | |
// |<----- Request ------+ | |
const redemptionContext = crypto.getRandomValues(new Uint8Array(32));
const originInfo = ['origin.example.com', 'origin2.example.com'];
const tokChl = new TokenChallenge(tokenType, issuer.name, redemptionContext, originInfo);
const tokChl = origin.createTokenChallenge(issuer.name, redemptionContext);
// +-- TokenChallenge -->| | |
// | |<== Attestation ==>| |
// | | | |
Expand All @@ -40,7 +39,7 @@ export async function privateVerifiableTokens(): Promise<void> {
const token = await client.finalize(tokRes);
// |<-- Request+Token ---+ | |
// | | | |
const isValid = await issuer.verify(token);
const isValid = await origin.verify(token, keys.privateKey);

console.log('Private-Verifiable tokens');
console.log(` Suite: ${TOKEN_TYPES.VOPRF.name}`);
Expand Down
17 changes: 11 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cloudflare/privacypass-ts",
"version": "0.6.0",
"version": "0.7.0-beta.0",
"description": "privacypass-ts: A TypeScript Library for the Privacy Pass Issuance Protocol",
"author": "Armando Faz <armfazh@cloudflare.com>",
"contributors": [
Expand Down Expand Up @@ -41,6 +41,7 @@
"@cloudflare/voprf-ts": "1.0.0",
"asn1-parser": "1.1.8",
"asn1js": "3.0.5",
"quicvarint": "0.1.4",
"rfc4648": "1.5.3"
},
"devDependencies": {
Expand Down
Loading
Loading