Skip to content

Commit

Permalink
feat: @cloudflare/voprf-ts/facade using CryptoProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
sublimator authored and thibmeu committed Jan 15, 2024
1 parent f277b02 commit 492e8b7
Show file tree
Hide file tree
Showing 51 changed files with 1,727 additions and 470 deletions.
17 changes: 14 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ on:

jobs:
testing:
name: Testing on Node v${{ matrix.node }}
name: Testing on Node v${{ matrix.node }} / CRYPTO_PROVIDER_ARG_REQUIRED=${{ matrix.crypto_arg_required }}
runs-on: ubuntu-latest
strategy:
matrix:
node: [20, 18]
node: [ 20, 18 ]
crypto_arg_required: [ true, false ]
steps:
- name: Checking out
uses: actions/checkout@v3
Expand All @@ -28,14 +29,24 @@ jobs:
- name: Install NPM dependencies
run: npm ci

- name: Modify buildSettings.ts for testing
run: sed -i "s/CRYPTO_PROVIDER_ARG_REQUIRED = false/CRYPTO_PROVIDER_ARG_REQUIRED = ${{ matrix.crypto_arg_required }}/g" src/buildSettings.ts

- name: Check lint
run: npm run lint

- name: Check build
run: npm run build

- name: Check build others
if: matrix.crypto_arg_required == false
run: npm run build:others

- name: Run NPM tests
run: npm test

- name: Check examples
run: npm run examples
if: matrix.crypto_arg_required == false
run: |
npm run examples
npm run examples:facade
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ Finally, the client can produce the output[s] of the OPRF protocol using the ser
const [output] = await client.finalize(finData, evaluation);
```

### Facade API

See [examples](examples/facade/index.ts)

### Development

| Task | NPM scripts |
Expand Down
8 changes: 4 additions & 4 deletions bench/group.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// at https://opensource.org/licenses/BSD-3-Clause

import Benchmark from 'benchmark'
import { Oprf } from '../src/index.js'
import { type CryptoProvider } from '@cloudflare/voprf-ts'

function asyncFn(call: CallableFunction) {
return {
Expand All @@ -16,13 +16,13 @@ function asyncFn(call: CallableFunction) {
}
}

export async function benchGroup(bs: Benchmark.Suite) {
export async function benchGroup(provider: CryptoProvider, bs: Benchmark.Suite) {
const te = new TextEncoder()
const msg = te.encode('msg')
const dst = te.encode('dst')

for (const id of Oprf.Group.supportedGroups) {
const gg = Oprf.Group.fromID(id)
for (const id of provider.Group.supportedGroups) {
const gg = provider.Group.get(id)
const k = await gg.randomScalar()
const P = gg.mulGen(k)
const Q = P.mul(k)
Expand Down
45 changes: 32 additions & 13 deletions bench/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,48 @@
// at https://opensource.org/licenses/BSD-3-Clause

import Benchmark from 'benchmark'
import { webcrypto } from 'node:crypto'

import { benchGroup } from './group.bench.js'
import { benchOPRF } from './oprf.bench.js'
import { webcrypto } from 'node:crypto'
import { getCryptoProviders } from './testProviders.js'

import { type CryptoProvider } from '../src/index.js'

if (typeof crypto === 'undefined') {
global.crypto = webcrypto as unknown as Crypto
Object.assign(global, { crypto: webcrypto })
}

async function bench() {
async function bench(provider: CryptoProvider) {
const bs = new Benchmark.Suite()
await benchOPRF(provider, bs)
await benchGroup(provider, bs)

await benchOPRF(bs)
await benchGroup(bs)
return new Promise<unknown>((resolve, reject) => {
bs.on('cycle', (ev: Benchmark.Event) => {
console.log(`${provider.id}/${String(ev.target)}`)
})
bs.on('error', (event: Benchmark.Event) => {
bs.abort()
reject(new Error(`error: ${String(event.target)}`))
})
bs.on('complete', resolve)

bs.on('cycle', (ev: Benchmark.Event) => {
console.log(String(ev.target))
bs.run({ async: false })
})
}

bs.run({ async: false })
async function runBenchmarksSerially() {
try {
for (const provider of getCryptoProviders()) {
await bench(provider)
}
} catch (_e) {
const e = _e as Error
console.log(`Error: ${e.message}`)
console.log(`Stack: ${e.stack}`)
process.exit(1)
}
}

bench().catch((e: Error) => {
console.log(`Error: ${e.message}`)
console.log(`Stack: ${e.stack}`)
process.exit(1)
})
void runBenchmarksSerially()
28 changes: 15 additions & 13 deletions bench/oprf.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
// at https://opensource.org/licenses/BSD-3-Clause

import {
type CryptoProvider,
Oprf,
OPRFClient,
OPRFServer,
Oprf,
POPRFClient,
POPRFServer,
POPRFClient,
VOPRFClient,
VOPRFServer,
generatePublicKey,
getSupportedSuites,
randomPrivateKey
} from '../src/index.js'

Expand All @@ -27,36 +29,36 @@ function asyncFn(call: CallableFunction) {
}
}

export async function benchOPRF(bs: Benchmark.Suite) {
export async function benchOPRF(provider: CryptoProvider, bs: Benchmark.Suite) {
const te = new TextEncoder()
const input = te.encode('This is the client input')

for (const [mode, m] of Object.entries(Oprf.Mode)) {
for (const [suite, id] of Object.entries(Oprf.Suite)) {
const privateKey = await randomPrivateKey(id)
const publicKey = generatePublicKey(id, privateKey)
for (const id of getSupportedSuites(provider.Group)) {
const privateKey = await randomPrivateKey(id, provider)
const publicKey = generatePublicKey(id, privateKey, provider)
let server: OPRFServer | VOPRFServer | POPRFServer
let client: OPRFClient | VOPRFClient | POPRFClient

switch (m) {
case Oprf.Mode.OPRF:
server = new OPRFServer(id, privateKey)
client = new OPRFClient(id)
server = new OPRFServer(id, privateKey, provider)
client = new OPRFClient(id, provider)
break

case Oprf.Mode.VOPRF:
server = new VOPRFServer(id, privateKey)
client = new VOPRFClient(id, publicKey)
server = new VOPRFServer(id, privateKey, provider)
client = new VOPRFClient(id, publicKey, provider)
break
case Oprf.Mode.POPRF:
server = new POPRFServer(id, privateKey)
client = new POPRFClient(id, publicKey)
server = new POPRFServer(id, privateKey, provider)
client = new POPRFClient(id, publicKey, provider)
break
}

const [finData, evalReq] = await client.blind([input])
const evaluatedElement = await server.blindEvaluate(evalReq)
const prefix = mode + '/' + suite + '/'
const prefix = mode + '/' + id + '/'

bs.add(
prefix + 'blind ',
Expand Down
16 changes: 16 additions & 0 deletions bench/testProviders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CryptoNoble } from '../src/cryptoNoble.js'
import { CryptoSjcl } from '../src/cryptoSjcl.js'

const allProviders = [CryptoNoble, CryptoSjcl]
const providerMatch = process.env.CRYPTO_PROVIDER

export function getCryptoProviders() {
const names = allProviders.map((p) => p.id)
const testProviders = allProviders.filter(
(provider) => !providerMatch || provider.id === providerMatch
)
if (testProviders.length === 0) {
throw new Error(`no CryptoProvider with name === ${providerMatch} among [${names}]`)
}
return testProviders
}
11 changes: 8 additions & 3 deletions bench/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
{
"extends": "../tsconfig.json",
"include": [
"."
],
"compilerOptions": {
"paths": {
"@cloudflare/voprf-ts": ["../src/index.js"],
"@cloudflare/voprf-ts/crypto-noble": ["../src/cryptoNoble.js"],
"@cloudflare/voprf-ts/facade": ["../src/facade/index.js"]
}
},
"include": ["."],
"references": [
{
"path": ".."
Expand Down
Loading

0 comments on commit 492e8b7

Please sign in to comment.