Skip to content

Commit

Permalink
Merge pull request #72 from piotr-roslaniec/tpke-wasm-api-example
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec authored Feb 27, 2023
2 parents 093f17e + 707f460 commit a6caaad
Show file tree
Hide file tree
Showing 28 changed files with 7,794 additions and 54 deletions.
139 changes: 139 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Adopted from: https://github.com/nucypher/rust-umbral/blob/master/.github/workflows/wheels.yml

name: Wheels

on: workflow_dispatch

jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest, macos-11 ]

env:
CIBW_BUILD_VERBOSITY: 1
CIBW_BEFORE_ALL_LINUX: "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && yum install -y openssl-devel"
CIBW_BEFORE_BUILD_LINUX: "pip3 install --upgrade keyrings.alt"
CIBW_ARCHS_LINUX: "x86_64"
CIBW_ENVIRONMENT: 'PATH="$PATH:$HOME/.cargo/bin"'
CIBW_SKIP: "cp36-* pp* *-win32 *musllinux*" # only using manylinux to build

steps:
- uses: actions/checkout@v2

- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- if: runner.os == 'Windows'
run: |
echo 'PATH=/c/Python38:/c/Python38/Scripts:/c/Strawberry/perl/site/bin:/c/Strawberry/perl/bin:/c/Strawberry/c/bin:$PATH' >> $GITHUB_ENV
echo 'RUSTFLAGS=-Ctarget-feature=+crt-static' >> $GITHUB_ENV
echo 'RUSTFLAGS=-Ctarget-feature=+crt-static' >> $GITHUB_ENV
echo 'CIBW_BEFORE_BUILD=python -m pip install --upgrade pip' >> $GITHUB_ENV
- if: runner.os != 'Linux'
name: Setup env when not using docker
run: |
python -m pip install --upgrade wheel setuptools setuptools-rust
- if: runner.os == 'Linux'
name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v1
with:
image: tonistiigi/binfmt:latest
platforms: arm64

- uses: actions/setup-python@v2
name: Install Python
with:
python-version: '3.8'

- name: Install cibuildwheel
run: |
# Install cibuildwheel from git for CIBW_ARCHS_LINUX support
python -m pip install cibuildwheel==2.9.0
- if: runner.os == 'Linux'
run: |
cp -r ./ferveo ./ferveo-python/ferveo
cp -r ./ferveo-common ./ferveo-python/ferveo-common
cp -r ./tpke ./ferveo-python/tpke
- if: runner.os == 'Linux'
working-directory: ./ferveo-python
name: Relocate dependencies in cargo.toml
run: |
sed -i 's/..\/ferveo/.\/ferveo/g' Cargo.toml
sed -i 's/..\/tpke/.\/tpke/g' Cargo.toml
- name: Build wheels
working-directory: ./ferveo-python
run: |
pwd
ls -la
cd ferveo-python && python -m cibuildwheel --output-dir wheelhouse
- uses: actions/upload-artifact@v2
with:
path: ./ferveo-python/wheelhouse/*.whl

build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- uses: actions/setup-python@v2
name: Install Python
with:
python-version: '3.8'

- name: Install setuptools and setuptools-rust
working-directory: ./ferveo-python
run: |
python -m pip install --upgrade wheel setuptools setuptools-rust
# Assuming here that the version of the Python bindings
# is matched to the version of the main Rust crate (as it should be at all times),
# and we are running this at a release commit.
- name: Replace the relative path to `ferveo` in Cargo.toml with the specific version
working-directory: ./ferveo-python
run: python replace_version.py relative-to-published

- name: Build sdist
working-directory: ./ferveo-python
run: python setup.py sdist

# Roll back the changes
- name: Replace the specific version of `ferveo` in Cargo.toml with the relative path
if: always()
working-directory: ./ferveo-python
run: python replace_version.py published-to-relative

- uses: actions/upload-artifact@v2
with:
path: ./ferveo-python/dist/*.tar.gz

upload_pypi:
needs: [ build_wheels, build_sdist ]
runs-on: ubuntu-latest

steps:
- uses: actions/download-artifact@v2
with:
name: artifact
path: dist
- uses: actions/download-artifact@v2
with:
name: artifact
path: wheelhouse

- uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.pypi_password }}
33 changes: 32 additions & 1 deletion .github/workflows/workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,35 @@ jobs:
- run: cargo install wasm-pack
- run: wasm-pack test --node
working-directory: tpke-wasm

yarn-test:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
target:
- wasm32-unknown-unknown
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
- run: cargo install wasm-pack
- run: wasm-pack build --target nodejs
working-directory: tpke-wasm
- uses: borales/[email protected]
with:
cmd: --cwd tpke-wasm/examples/node install
- uses: borales/[email protected]
with:
cmd: --cwd tpke-wasm/examples/node build
- uses: borales/[email protected]
with:
cmd: --cwd tpke-wasm/examples/node test

codecov:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -149,10 +178,12 @@ jobs:
restore-keys: ${{ runner.os }}-cargo-
- name: Run benchmark for base branch comparison
uses: boa-dev/criterion-compare-action@v3
if: github.event_name == 'pull_request'
# Only PRs to main
if: github.event_name == 'pull_request' && github.ref == 'refs/heads/main' && github.repository == 'nucypher/ferveo'
with:
cwd: ${{ matrix.component }}
branchName: ${{ github.base_ref }}
features: "test-common"

# The next steps have been adapted from https://raw.githubusercontent.com/unicode-org/icu4x/main/.github/workflows/build-test.yml

Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion ferveo-python/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "ferveo-python"
authors = ["Piotr Roslaniec <[email protected]>"]
version = "0.1.0"
version = "0.1.1"
edition = "2018"

[lib]
Expand Down
2 changes: 1 addition & 1 deletion ferveo-python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
description="Ferveo DKG scheme",
long_description=long_description,
long_description_content_type="text/markdown",
version="0.1.0",
version="0.1.1",
author="Piotr Roslaniec",
author_email="[email protected]",
url="https://github.com/nucypher/ferveo/tree/master/ferveo-python",
Expand Down
6 changes: 6 additions & 0 deletions ferveo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ digest = { version = "0.10.0", features = ["alloc"] }
development = ["pprof"]
build = ["rand_old"]

[lib]
bench = false

[features]
test-common = []

[[example]]
name = "pvdkg"
path = "examples/pvdkg.rs"
Expand Down
4 changes: 3 additions & 1 deletion tpke-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[package]
name = "tpke-wasm"
version = "0.1.0"
version = "0.1.0-alpha.1"
authors = ["Piotr Roslaniec <[email protected]>"]
edition = "2021"
license = "GPL-3.0-only"
readme = "README.md"
categories = ["cryptography", "no-std"]
repository = "https://github.com/nucypher/ferveo"
description = "WASM bindings for group-threshold-cryptography crate"

[lib]
crate-type = ["cdylib", "rlib"]
Expand Down
10 changes: 10 additions & 0 deletions tpke-wasm/examples/browser/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/node_modules/
/build/
/lib/
/dist/
/docs/
.idea/*

.DS_Store
coverage
*.log
17 changes: 17 additions & 0 deletions tpke-wasm/examples/browser/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# `tpke-wasm` in the browser:

## Usage

Make sure `pkg` is build with correct target:
```bash
cd ../../
wasm-pack build --target web
```

Install dependencies and run tests:
```bash
$ yarn install
$ yarn start
```

Visit https://localhost:8080/ in your browser.
5 changes: 5 additions & 0 deletions tpke-wasm/examples/browser/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import("./index.js")
.catch(e => console.error("Error importing `index.js`:", e));
12 changes: 12 additions & 0 deletions tpke-wasm/examples/browser/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>tpke-wasm example</title>
</head>
<body>
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
<script src="./bootstrap.js"></script>
<h1>Check console for results</h1>
</body>
</html>
84 changes: 84 additions & 0 deletions tpke-wasm/examples/browser/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
Ciphertext,
decryptWithSharedSecret,
Dkg,
encrypt,
SharedSecretSimpleBuilder,
DecryptionShareSimple,
} from "tpke-wasm";

const zip = (a, b) => a.map((k, i) => [k, b[i]]);

const areEqual = (first, second) =>
first.length === second.length && first.every((value, index) => value === second[index]);

const sharesNum = 16;
const threshold = (sharesNum * 2) / 3;
const msg = new TextEncoder().encode("my-msg");
const aad = new TextEncoder().encode("my-aad");

const dkg = new Dkg(threshold, sharesNum);

//
// On the client side
//

// Encrypt the message
const ciphertext = encrypt(msg, aad, dkg.public_key);

// Serialize and send to validators
const ciphertext_bytes = ciphertext.toBytes();

//
// On the server side
//

const ciphertext2 = Ciphertext.fromBytes(ciphertext_bytes);
console.assert(areEqual(ciphertext.toBytes(), ciphertext2.toBytes()));

// Create decryption shares

const decryptionShares = [];
for (let i = 0; i < threshold; i++) {
const share = dkg.makeDecryptionShareSimple(ciphertext, aad, i);
decryptionShares.push(share);
}

const domainPoints = [];
for (let i = 0; i < threshold; i++) {
const point = dkg.getDomainPoint(i);
domainPoints.push(point);
}

// Serialize and send back to client
const decryptionSharesBytes = decryptionShares.map((s) => s.toBytes());

//
// On the client side
//

const decryptionShares2 = decryptionSharesBytes.map((b) =>
DecryptionShareSimple.fromBytes(b)
);
zip(decryptionShares, decryptionShares2).map(([s1, s2]) =>
console.assert(areEqual(s1.toBytes(), s2.toBytes()))
)

// Combine shares into a shared secret
const ssBuilder = new SharedSecretSimpleBuilder(threshold);
decryptionShares.forEach((share) => ssBuilder.addDecryptionShare(share));

domainPoints.forEach((point) => ssBuilder.addDomainPoint(point));

const shared_secret = ssBuilder.build();

// Decrypt the message
const plaintext = decryptWithSharedSecret(
ciphertext,
aad,
shared_secret,
dkg.gInv
);
console.assert(areEqual(plaintext, msg));

console.log("Success! 🎉")
Loading

0 comments on commit a6caaad

Please sign in to comment.