Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e14e1ca31 | ||
|
|
e6e53bf679 | ||
|
|
80cd4709ee | ||
|
|
20dd8a2485 | ||
|
|
bbd71fd1fb |
137
.github/workflows/artifacts.yml
vendored
@ -1,137 +0,0 @@
|
||||
name: Release artifacts
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
build_linux_android:
|
||||
name: Build Linux + Android
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure git to use HTTPS
|
||||
run: git config --global url."https://${{ secrets.REPO_ACCESS_TOKEN }}:x-oauth-basic@github.com".insteadOf ssh://git@github.com
|
||||
|
||||
- name: Install pre-requisites
|
||||
run: |
|
||||
cargo install --version=1.0.0 cargo-ndk
|
||||
rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android
|
||||
|
||||
- name: Build Android
|
||||
run: |
|
||||
cargo ndk --target aarch64-linux-android --platform 21 -- build --release
|
||||
cargo ndk --target armv7-linux-androideabi --platform 19 -- build --release
|
||||
cargo ndk --target i686-linux-android --platform 19 -- build --release
|
||||
cargo ndk --target x86_64-linux-android --platform 21 -- build --release
|
||||
find ./target -name libzkgroup.so | xargs zip libzkgroup-android.zip
|
||||
env:
|
||||
RUSTFLAGS: -C link-arg=-s
|
||||
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk/
|
||||
ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk-bundle/
|
||||
|
||||
- name: Read .nvmrc
|
||||
id: node_version
|
||||
working-directory: ffi/node
|
||||
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '${{ steps.node_version.outputs.NODE_VERSION }}'
|
||||
|
||||
- name: Build Linux
|
||||
working-directory: ffi/node
|
||||
run: |
|
||||
npm --version
|
||||
node --version
|
||||
make libzkgroup
|
||||
|
||||
- name: Upload Android
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: libzkgroup-android.zip
|
||||
asset_name: libzkgroup-android.zip
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
- name: Upload Linux
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ffi/node/libzkgroup-x64.so
|
||||
asset_name: libzkgroup-x64.so
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
build_windows:
|
||||
name: Build Windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure git to use HTTPS
|
||||
run: git config --global url."https://${{ secrets.REPO_ACCESS_TOKEN }}:x-oauth-basic@github.com".insteadOf ssh://git@github.com
|
||||
|
||||
- name: Read .nvmrc
|
||||
id: node_version
|
||||
working-directory: ffi/node
|
||||
run: echo "::set-output name=NODE_VERSION::$(cat .nvmrc)"
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '${{ steps.node_version.outputs.NODE_VERSION }}'
|
||||
|
||||
- name: Build
|
||||
working-directory: ffi/node
|
||||
run: |
|
||||
npm --version
|
||||
node --version
|
||||
make libzkgroup
|
||||
|
||||
- name: Upload
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ffi/node/libzkgroup-x64.dll
|
||||
asset_name: libzkgroup-x64.dll
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
build_macOS:
|
||||
name: Build macOS (Node)
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure git to use HTTPS
|
||||
run: git config --global url."https://${{ secrets.REPO_ACCESS_TOKEN }}:x-oauth-basic@github.com".insteadOf ssh://git@github.com
|
||||
|
||||
- name: Read .nvmrc
|
||||
id: node_version
|
||||
working-directory: ffi/node
|
||||
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '${{ steps.node_version.outputs.NODE_VERSION }}'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm --version
|
||||
node --version
|
||||
cd ffi/node
|
||||
make libzkgroup
|
||||
|
||||
- name: Upload macOS
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ffi/node/libzkgroup-x64.dylib
|
||||
asset_name: libzkgroup-x64.dylib
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
15
.github/workflows/formatting.yml
vendored
@ -1,15 +0,0 @@
|
||||
name: Code Formatting
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
|
||||
code_formatting:
|
||||
name: Code Formatting
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run rustfmt
|
||||
run: |
|
||||
rustup component add rustfmt
|
||||
cargo fmt -- --check
|
||||
77
.github/workflows/tests.yml
vendored
@ -1,77 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
|
||||
test_misc:
|
||||
name: Rust + Java + Node
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Configure git to use HTTPS
|
||||
run: git config --global url."https://${{ secrets.REPO_ACCESS_TOKEN }}:x-oauth-basic@github.com".insteadOf ssh://git@github.com
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Run clippy
|
||||
run: |
|
||||
rustup component add clippy
|
||||
cargo clippy -- -D warnings
|
||||
|
||||
- name: Test Rust
|
||||
run: cargo test
|
||||
|
||||
- name: Test Java
|
||||
run: |
|
||||
cargo install --version=1.0.0 cargo-ndk
|
||||
rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android
|
||||
./gradlew test
|
||||
env:
|
||||
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk/
|
||||
ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk-bundle/
|
||||
|
||||
- name: Read .nvmrc
|
||||
id: node_version
|
||||
working-directory: ffi/node
|
||||
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '${{ steps.node_version.outputs.NODE_VERSION }}'
|
||||
|
||||
- name: Test Node
|
||||
working-directory: ffi/node
|
||||
run: |
|
||||
npm --version
|
||||
node --version
|
||||
make libzkgroup
|
||||
make test
|
||||
|
||||
test_ios:
|
||||
name: iOS
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup rust toolchain
|
||||
run: rustup show
|
||||
|
||||
- name: Run pod lint
|
||||
# No import validation because it tries to build unsupported platforms (like 32-bit iOS).
|
||||
run: pod lib lint --verbose --platforms=ios --skip-import-validation --allow-warnings
|
||||
17
.gitignore
vendored
@ -1,17 +0,0 @@
|
||||
__pycache__
|
||||
build
|
||||
target
|
||||
.idea
|
||||
.gradle
|
||||
ffi/java/.idea
|
||||
ffi/java/build
|
||||
ffi/java/out
|
||||
ffi/java/src/main/resources
|
||||
ffi/java/src/otherPlatformLibraries/resources
|
||||
*.iml
|
||||
ffi/node/node_modules
|
||||
ffi/node/dist
|
||||
.DS_Store
|
||||
.project
|
||||
.settings
|
||||
/local.properties
|
||||
1022
Cargo.lock
generated
@ -1,9 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2020 Signal Messenger, LLC.
|
||||
# All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
|
||||
[workspace]
|
||||
members = ["rust"]
|
||||
87
Dockerfile
@ -1,87 +0,0 @@
|
||||
FROM debian:stretch
|
||||
|
||||
COPY docker/ docker/
|
||||
COPY docker/apt.conf docker/sources.list /etc/apt/
|
||||
|
||||
RUN dpkg --add-architecture i386
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
software-properties-common
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
apt-transport-https \
|
||||
build-essential \
|
||||
git \
|
||||
curl \
|
||||
wget \
|
||||
gpg-agent \
|
||||
openssh-client \
|
||||
unzip
|
||||
|
||||
# Install pinned dependencies
|
||||
RUN apt-get install -y $(cat docker/dependencies.txt)
|
||||
RUN docker/print-versions.sh docker/dependencies.txt
|
||||
|
||||
RUN rm -rf /var/lib/apt/lists/* && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean
|
||||
|
||||
ARG UID
|
||||
ARG GID
|
||||
|
||||
# Create a user to map the host user to.
|
||||
RUN groupadd -o -g "${GID}" zkgroup \
|
||||
&& useradd -m -o -u "${UID}" -g "${GID}" -s /bin/bash zkgroup
|
||||
|
||||
USER zkgroup
|
||||
ENV HOME /home/zkgroup
|
||||
ENV USER zkgroup
|
||||
ENV SHELL /bin/bash
|
||||
|
||||
WORKDIR /home/zkgroup
|
||||
|
||||
# Rust setup...
|
||||
COPY rust-toolchain.toml rust-toolchain.toml
|
||||
ARG RUSTUP_SHA256=3dc5ef50861ee18657f9db2eeb7392f9c2a6c95c90ab41e45ab4ca71476b4338
|
||||
ARG CARGO_NDK_VERSION=1.0.0
|
||||
ENV PATH="/home/zkgroup/.cargo/bin:${PATH}"
|
||||
|
||||
RUN curl -f https://static.rust-lang.org/rustup/archive/1.24.3/x86_64-unknown-linux-gnu/rustup-init -o /tmp/rustup-init \
|
||||
&& echo "${RUSTUP_SHA256} /tmp/rustup-init" | sha256sum -c - \
|
||||
&& chmod a+x /tmp/rustup-init \
|
||||
&& /tmp/rustup-init -y --profile default --default-toolchain nightly-2021-09-19 \
|
||||
&& rm -rf /tmp/rustup-init \
|
||||
&& rustup component add rust-src \
|
||||
&& rustup target add aarch64-apple-darwin aarch64-apple-ios aarch64-apple-ios-sim aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-apple-darwin x86_64-apple-ios x86_64-linux-android x86_64-unknown-linux-gnu \
|
||||
&& cargo install --version ${CARGO_NDK_VERSION} cargo-ndk
|
||||
|
||||
# Android SDK setup...
|
||||
ARG ANDROID_SDK_FILENAME=commandlinetools-linux-6200805_latest.zip
|
||||
ARG ANDROID_SDK_SHA=f10f9d5bca53cc27e2d210be2cbc7c0f1ee906ad9b868748d74d62e10f2c8275
|
||||
ARG ANDROID_API_LEVELS=android-28
|
||||
ARG ANDROID_BUILD_TOOLS_VERSION=28.0.3
|
||||
ARG NDK_VERSION=21.0.6113669
|
||||
ENV ANDROID_HOME /home/zkgroup/android-sdk
|
||||
ENV NDK_HOME ${ANDROID_HOME}/ndk/${NDK_VERSION}
|
||||
ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
||||
|
||||
RUN wget -q https://dl.google.com/android/repository/${ANDROID_SDK_FILENAME} \
|
||||
&& echo "${ANDROID_SDK_SHA} ${ANDROID_SDK_FILENAME}" | sha256sum -c - \
|
||||
&& unzip -q ${ANDROID_SDK_FILENAME} -d android-sdk \
|
||||
&& rm -rf ${ANDROID_SDK_FILENAME} \
|
||||
&& echo y | ./android-sdk/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "platforms;${ANDROID_API_LEVELS}" \
|
||||
&& ./android-sdk/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
&& ./android-sdk/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools" \
|
||||
&& ./android-sdk/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "ndk;${NDK_VERSION}"
|
||||
|
||||
# Pre-download Gradle.
|
||||
COPY gradle gradle
|
||||
COPY gradlew .
|
||||
RUN ./gradlew --version
|
||||
|
||||
# Convert ssh to https for git dependency access without a key.
|
||||
RUN git config --global url."https://github".insteadOf ssh://git@github
|
||||
|
||||
CMD [ "/bin/bash" ]
|
||||
628
LICENSE
@ -1,628 +0,0 @@
|
||||
This software is provided under:
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
The complete license text:
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
88
Makefile
@ -1,88 +0,0 @@
|
||||
CARGO ?= cargo
|
||||
DOCKER ?= docker
|
||||
|
||||
.PHONY: default android_so server_so mac_dylib docker
|
||||
|
||||
default: docker
|
||||
|
||||
android_so:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo ndk --target aarch64-linux-android --platform 21 -- build --release
|
||||
RUSTFLAGS='-C link-arg=-s' cargo ndk --target armv7-linux-androideabi --platform 19 -- build --release
|
||||
RUSTFLAGS='-C link-arg=-s' cargo ndk --target i686-linux-android --platform 19 -- build --release
|
||||
RUSTFLAGS='-C link-arg=-s' cargo ndk --target x86_64-linux-android --platform 21 -- build --release
|
||||
mkdir -p ffi/android/lib/src/main/jniLibs/armeabi-v7a/
|
||||
cp target/armv7-linux-androideabi/release/libzkgroup.so \
|
||||
ffi/android/lib/src/main/jniLibs/armeabi-v7a/
|
||||
mkdir -p ffi/android/lib/src/main/jniLibs/arm64-v8a/
|
||||
cp target/aarch64-linux-android/release/libzkgroup.so \
|
||||
ffi/android/lib/src/main/jniLibs/arm64-v8a/
|
||||
mkdir -p ffi/android/lib/src/main/jniLibs/x86/
|
||||
cp target/i686-linux-android/release/libzkgroup.so \
|
||||
ffi/android/lib/src/main/jniLibs/x86/
|
||||
mkdir -p ffi/android/lib/src/main/jniLibs/x86_64/
|
||||
cp target/x86_64-linux-android/release/libzkgroup.so \
|
||||
ffi/android/lib/src/main/jniLibs/x86_64/
|
||||
|
||||
server_so:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo build --target x86_64-unknown-linux-gnu --release
|
||||
mkdir -p ffi/java/src/main/resources/
|
||||
cp target/x86_64-unknown-linux-gnu/release/libzkgroup.so ffi/java/src/main/resources/
|
||||
|
||||
server_so_simd:
|
||||
cd rust && RUSTFLAGS='-C link-arg=-s -C target_feature=+avx512ifma' cargo +nightly build --target x86_64-unknown-linux-gnu --release --no-default-features --features "simd_backend"
|
||||
|
||||
# @deprecated build
|
||||
mac_dylib:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo build --target x86_64-apple-darwin --release
|
||||
mkdir -p ffi/java/src/main/resources/
|
||||
cp target/x86_64-apple-darwin/release/libzkgroup.dylib ffi/java/src/main/resources/
|
||||
|
||||
libzkgroup:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo build --release
|
||||
|
||||
DOCKER_IMAGE := zkgroup-builder
|
||||
|
||||
docker_build:
|
||||
$(DOCKER) build --build-arg UID=$$(id -u) --build-arg GID=$$(id -g) \
|
||||
-t $(DOCKER_IMAGE) .
|
||||
|
||||
docker: DOCKER_EXTRA=$(shell [ -L build ] && P=$$(readlink build) && echo -v $$P/:$$P )
|
||||
docker: docker_build
|
||||
$(DOCKER) run --rm --user $$(id -u):$$(id -g) \
|
||||
--env "MAKEFLAGS=$(MAKEFLAGS)" \
|
||||
-v `pwd`/:/home/zkgroup/src $(DOCKER_EXTRA) $(DOCKER_IMAGE) \
|
||||
sh -c "cd src; ./gradlew build"
|
||||
|
||||
docker_test: docker_build
|
||||
$(DOCKER) run --rm --user $$(id -u):$$(id -g) \
|
||||
--env "MAKEFLAGS=$(MAKEFLAGS)" \
|
||||
-v `pwd`/:/home/zkgroup/src $(DOCKER_EXTRA) $(DOCKER_IMAGE) \
|
||||
sh -c "cd src; ./gradlew test"
|
||||
|
||||
|
||||
SONATYPE_USERNAME ?=
|
||||
SONATYPE_PASSWORD ?=
|
||||
KEYRING_FILE ?=
|
||||
SIGNING_KEY ?=
|
||||
SIGNING_KEY_PASSWORD ?=
|
||||
|
||||
publish: DOCKER_EXTRA = $(shell [ -L build ] && P=$$(readlink build) && echo -v $$P/:$$P )
|
||||
publish: KEYRING_VOLUME := $(dir $(KEYRING_FILE))
|
||||
publish: KEYRING_FILE_ROOT := $(notdir $(KEYRING_FILE))
|
||||
publish:
|
||||
@[ -n "$(SONATYPE_USERNAME)" ] || ( echo "SONATYPE_USERNAME is not set" && false )
|
||||
@[ -n "$(SONATYPE_PASSWORD)" ] || ( echo "SONATYPE_PASSWORD is not set" && false )
|
||||
@[ -n "$(KEYRING_FILE)" ] || ( echo "KEYRING_FILE is not set" && false )
|
||||
@[ -n "$(SIGNING_KEY)" ] || ( echo "SIGNING_KEY is not set" && false )
|
||||
@[ -n "$(SIGNING_KEY_PASSWORD)" ] || ( echo "SIGNING_KEY_PASSWORD is not set" && false )
|
||||
$(DOCKER) run --rm --user $$(id -u):$$(id -g) \
|
||||
--env "MAKEFLAGS=$(MAKEFLAGS)" \
|
||||
-v `pwd`/:/home/zkgroup/src $(DOCKER_EXTRA) \
|
||||
-v $(KEYRING_VOLUME):/home/zkgroup/keyring \
|
||||
$(DOCKER_IMAGE) \
|
||||
sh -c "cd src; ./gradlew uploadArchives \
|
||||
-PwhisperSonatypeUsername='$(SONATYPE_USERNAME)' \
|
||||
-PwhisperSonatypePassword='$(SONATYPE_PASSWORD)' \
|
||||
-Psigning.secretKeyRingFile='/home/zkgroup/keyring/$(KEYRING_FILE_ROOT)' \
|
||||
-Psigning.keyId='$(SIGNING_KEY)' \
|
||||
-Psigning.password='$(SIGNING_KEY_PASSWORD)'"
|
||||
35
README.md
@ -1,34 +1,3 @@
|
||||
Library for the Signal Private Group System.
|
||||
**ZKGroup has moved to [libsignal][],** under the crate name `zkgroup`, at version 0.9.0.
|
||||
|
||||
Work in progress. Subject to change without notice, use outside Signal not yet recommended.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This library provides zero-knowledge group functionality through several layers of APIs. From lower-level to higher-level:
|
||||
|
||||
* `internal.rs` provides the actual Rust implementations, based on Rust structures.
|
||||
|
||||
* `simpleapi.rs` provides wrapper functions around internal.rs functions that use `serde` to serialize/deseralize byte arrays into Rust structures.
|
||||
|
||||
* `ffiapi.rs` and `ffiapijava.rs` provide wrapper functions around `simpleapi.rs` functions to export them via C and JNI, respectively.
|
||||
|
||||
* The subdirectories under `ffi` contain code in various host languages for accessing the exported functions:
|
||||
|
||||
* Under `c` is a `zkgroup.h` header file.
|
||||
|
||||
* Under `android` is a `ZKGroup.java` file and instructions for building an aar.
|
||||
|
||||
* Under `node` is some example code for declaring the FFI functions in javascript.
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
The rust-toolchain.toml file should get things automatically setup for you
|
||||
provided you are using rustup. See it for the toolchain and channel and targets
|
||||
in use for this build.
|
||||
|
||||
Building Rust
|
||||
=============
|
||||
|
||||
Run `./gradlew tasks` and see `make` tasks under the "Rust tasks" group.
|
||||
[libsignal]: https://github.com/signalapp/libsignal
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
#
|
||||
# Be sure to run `pod spec lint credential.podspec' to ensure this is a
|
||||
# valid spec and to remove all comments including this before submitting the spec.
|
||||
#
|
||||
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
|
||||
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "ZKGroup"
|
||||
s.version = "0.8.1"
|
||||
s.summary = "Swift API for the Rust zkgroup crate."
|
||||
s.homepage = "https://signal.org/"
|
||||
s.license = { :type => "GPLv3", :file => "LICENSE" }
|
||||
s.authors = { "Signal iOS" => "ios@signal.org" }
|
||||
s.source = { :git => "https://github.com/signalapp/zkgroup.git", :tag => "v#{s.version}" }
|
||||
|
||||
s.swift_version = '5'
|
||||
s.platform = :ios, '10'
|
||||
|
||||
s.source_files = 'ffi/swift/Sources/**/*.{m,swift}'
|
||||
s.preserve_paths = [
|
||||
'target/*/release/libzkgroup.a',
|
||||
'ffi/swift/Sources/libzkgroup',
|
||||
]
|
||||
|
||||
s.pod_target_xcconfig = {
|
||||
'HEADER_SEARCH_PATHS' => '$(PODS_TARGET_SRCROOT)/ffi/swift/Sources/libzkgroup',
|
||||
# Duplicate this here to make sure the search path is passed on to Swift dependencies.
|
||||
'SWIFT_INCLUDE_PATHS' => '$(HEADER_SEARCH_PATHS)',
|
||||
|
||||
# Make sure we link the static library, not a dynamic one.
|
||||
# Use an extra level of indirection because CocoaPods messes with OTHER_LDFLAGS too.
|
||||
'LIBZKGROUP_FFI_LIB_IF_NEEDED' => '$(PODS_TARGET_SRCROOT)/target/$(CARGO_BUILD_TARGET)/release/libzkgroup.a',
|
||||
'OTHER_LDFLAGS' => '$(LIBZKGROUP_FFI_LIB_IF_NEEDED)',
|
||||
|
||||
'CARGO_BUILD_TARGET[sdk=iphonesimulator*][arch=arm64]' => 'aarch64-apple-ios-sim',
|
||||
'CARGO_BUILD_TARGET[sdk=iphonesimulator*][arch=*]' => 'x86_64-apple-ios',
|
||||
'CARGO_BUILD_TARGET[sdk=iphoneos*]' => 'aarch64-apple-ios',
|
||||
# Presently, there's no special SDK or arch for maccatalyst,
|
||||
# so we need to hackily use the "IS_MACCATALYST" build flag
|
||||
# to set the appropriate cargo target
|
||||
'CARGO_BUILD_TARGET_MAC_CATALYST_ARM_' => 'aarch64-apple-darwin',
|
||||
'CARGO_BUILD_TARGET_MAC_CATALYST_ARM_YES' => 'aarch64-apple-ios-macabi',
|
||||
'CARGO_BUILD_TARGET[sdk=macosx*][arch=arm64]' => '$(CARGO_BUILD_TARGET_MAC_CATALYST_ARM_$(IS_MACCATALYST))',
|
||||
'CARGO_BUILD_TARGET_MAC_CATALYST_X86_' => 'x86_64-apple-darwin',
|
||||
'CARGO_BUILD_TARGET_MAC_CATALYST_X86_YES' => 'x86_64-apple-ios-macabi',
|
||||
'CARGO_BUILD_TARGET[sdk=macosx*][arch=*]' => '$(CARGO_BUILD_TARGET_MAC_CATALYST_X86_$(IS_MACCATALYST))',
|
||||
|
||||
'ARCHS[sdk=iphonesimulator*]' => 'x86_64 arm64',
|
||||
'ARCHS[sdk=iphoneos*]' => 'arm64',
|
||||
}
|
||||
|
||||
s.user_target_xcconfig = {
|
||||
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
|
||||
}
|
||||
|
||||
s.script_phases = [
|
||||
{ :name => 'Check libzkgroup',
|
||||
:execution_position => :before_compile,
|
||||
:script => %q(
|
||||
test -e "${LIBZKGROUP_FFI_LIB_IF_NEEDED}" && exit 0
|
||||
if test -e "${PODS_TARGET_SRCROOT}/ffi/swift/build_ffi.sh"; then
|
||||
echo 'error: libzkgroup.a not built; run the following to build it:' >&2
|
||||
echo "CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET} \"${PODS_TARGET_SRCROOT}/ffi/swift/build_ffi.sh\" --release" >&2
|
||||
else
|
||||
echo 'error: libzkgroup.a not built; try re-running `pod install`' >&2
|
||||
fi
|
||||
false
|
||||
),
|
||||
}
|
||||
]
|
||||
|
||||
s.prepare_command = %q(
|
||||
set -euo pipefail
|
||||
CARGO_BUILD_TARGET=aarch64-apple-ios ffi/swift/build_ffi.sh --release
|
||||
CARGO_BUILD_TARGET=x86_64-apple-ios ffi/swift/build_ffi.sh --release
|
||||
CARGO_BUILD_TARGET=aarch64-apple-ios-sim ffi/swift/build_ffi.sh --release
|
||||
CARGO_BUILD_TARGET=x86_64-apple-ios-macabi ffi/swift/build_ffi.sh --release --build-std
|
||||
CARGO_BUILD_TARGET=aarch64-apple-ios-macabi ffi/swift/build_ffi.sh --release --build-std
|
||||
)
|
||||
|
||||
s.test_spec 'Tests' do |test_spec|
|
||||
test_spec.source_files = 'ffi/swift/Tests/**/*.{m,swift}'
|
||||
end
|
||||
end
|
||||
@ -1,58 +0,0 @@
|
||||
#
|
||||
# Copyright 2020 Signal Messenger, LLC.
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
#
|
||||
|
||||
# shellcheck shell=bash
|
||||
|
||||
check_rust() {
|
||||
if ! command -v rustup > /dev/null && [[ -d ~/.cargo/bin ]]; then
|
||||
# Try to find rustup in its default per-user install location.
|
||||
# This will be important when running from inside Xcode,
|
||||
# which does not run in a login shell context.
|
||||
PATH=~/.cargo/bin:$PATH
|
||||
fi
|
||||
|
||||
if ! command -v rustup > /dev/null; then
|
||||
if ! command -v cargo > /dev/null; then
|
||||
echo 'error: cargo not found in PATH; do you have Rust installed?' >&2
|
||||
echo 'note: we recommend installing Rust via rustup from https://rustup.rs/' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'warning: rustup not found in PATH; using cargo at' "$(command -v cargo)" >&2
|
||||
echo 'note: this project uses Rust toolchain' "'$(cat ./rust-toolchain)'" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${CARGO_BUILD_TARGET:-}" ]] && ! (rustup target list --installed | grep -q "${CARGO_BUILD_TARGET:-}"); then
|
||||
# TODO: We could remove this once M1 and catalyst support are promoted to tier 2
|
||||
if [[ -n "${BUILD_STD:-}" ]]; then
|
||||
echo "warning: Building std from source to support tier 3 target ${CARGO_BUILD_TARGET}." >&2
|
||||
else
|
||||
echo "error: Rust target ${CARGO_BUILD_TARGET} not installed" >&2
|
||||
echo 'note: get it by running' >&2
|
||||
printf "\n\t%s\n\n" "rustup +${RUSTUP_TOOLCHAIN:-$(cat ./rust-toolchain)} target add ${CARGO_BUILD_TARGET}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# usage: copy_built_library target/release signal_node out_dir/libsignal_node.node
|
||||
# copy_built_library target/release signal_jni out_dir/
|
||||
copy_built_library() {
|
||||
for possible_library_name in "lib$2.dylib" "lib$2.so" "$2.dll"; do
|
||||
possible_library_path="$1/${possible_library_name}"
|
||||
if [ -e "${possible_library_path}" ]; then
|
||||
out_dir=$(dirname "$3"x) # trailing x to distinguish directories from files
|
||||
echo_then_run mkdir -p "${out_dir}"
|
||||
echo_then_run cp "${possible_library_path}" "$3"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
echo_then_run() {
|
||||
echo "$@"
|
||||
"$@"
|
||||
}
|
||||
34
build.gradle
@ -1,34 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
task makeMac(type:Exec) {
|
||||
group 'Rust'
|
||||
description 'Build the mac library'
|
||||
|
||||
commandLine 'make', 'mac_dylib'
|
||||
}
|
||||
|
||||
task makeServer(type:Exec) {
|
||||
group 'Rust'
|
||||
description 'Build the server linux library'
|
||||
|
||||
commandLine 'make', 'server_so'
|
||||
}
|
||||
|
||||
task makeAndroid(type:Exec) {
|
||||
group 'Rust'
|
||||
description 'Build the android libraries'
|
||||
|
||||
commandLine 'make', 'android_so'
|
||||
}
|
||||
|
||||
task makeAll() {
|
||||
group 'Rust'
|
||||
description 'Build the android libraries'
|
||||
|
||||
dependsOn 'makeMac', 'makeServer', 'makeAndroid'
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
.PHONY: all
|
||||
all:
|
||||
$(MAKE) output
|
||||
$(MAKE) install
|
||||
$(MAKE) clean
|
||||
|
||||
.PHONY: output
|
||||
output:
|
||||
mkdir -p ffiapijava
|
||||
mkdir -p ffiapi
|
||||
mkdir -p java
|
||||
mkdir -p java/auth
|
||||
mkdir -p java/profiles
|
||||
mkdir -p java/groups
|
||||
mkdir -p java/internal
|
||||
mkdir -p java/receipts
|
||||
mkdir -p simpleapi
|
||||
mkdir -p swift
|
||||
python3 ./codegen.py
|
||||
rustfmt ffiapijava/ffiapijava.rs
|
||||
rustfmt ffiapi/ffiapi.rs
|
||||
rustfmt simpleapi/simpleapi.rs
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
cp ffiapijava/ffiapijava.rs ../rust/src/ffi/
|
||||
cp ffiapi/ffiapi.rs ../rust/src/ffi/
|
||||
cp simpleapi/simpleapi.rs ../rust/src/ffi/
|
||||
cp -r java/* ../ffi/java/src/main/java/org/signal/zkgroup
|
||||
cp -r swift/* ../ffi/swift/Sources/ZKGroup
|
||||
patch -d .. -p1 < codegen_hack.patch
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf ffiapijava
|
||||
rm -rf ffiapi
|
||||
rm -rf java
|
||||
rm -rf simpleapi
|
||||
rm -rf swift
|
||||
|
||||
.PHONY: clean-destination
|
||||
clean-destination:
|
||||
rm -rf ../ffi/java/src/main/java/org/signal/zkgroup
|
||||
mkdir -p ../ffi/java/src/main/java/org/signal/zkgroup
|
||||
rm -rf ../ffi/swift/Sources/ZKGroup
|
||||
mkdir -p ../ffi/swift/Sources/ZKGroup
|
||||
@ -1,380 +0,0 @@
|
||||
import codegen_java
|
||||
import codegen_ffiapi
|
||||
import codegen_ffiapijava
|
||||
import codegen_simpleapi
|
||||
import codegen_swift
|
||||
import sys
|
||||
|
||||
class Name:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def snake(self):
|
||||
return self.name
|
||||
|
||||
def camel(self):
|
||||
pieces = self.name.split("_")
|
||||
ret = ""
|
||||
for piece in pieces:
|
||||
ret += piece[0].upper() + piece[1:]
|
||||
return ret
|
||||
|
||||
def lower_camel(self):
|
||||
pieces = self.name.split("_")
|
||||
ret = ""
|
||||
first = True
|
||||
for piece in pieces:
|
||||
if first:
|
||||
ret += piece[0] + piece[1:]
|
||||
else:
|
||||
ret += piece[0].upper() + piece[1:]
|
||||
first = False
|
||||
return ret
|
||||
|
||||
class StaticMethodDescriptor:
|
||||
def __init__(self, method_name, return_type, return_name, params, rustCode, verification=False, runtime_error=False,
|
||||
return_size_increment=0):
|
||||
self.method_name = Name(method_name)
|
||||
self.return_type = return_type
|
||||
self.return_name = Name(return_name)
|
||||
self.params = params # list of (type, name) pairs
|
||||
self.rustCode = rustCode
|
||||
self.verification = verification
|
||||
self.runtime_error = runtime_error
|
||||
self.return_size_increment = return_size_increment
|
||||
|
||||
class MethodDescriptor:
|
||||
def __init__(self, method_name, return_type, return_name, params, rustCode, verification=False, runtime_error=False,
|
||||
unused_self=False, return_size_increment=0):
|
||||
self.method_name = Name(method_name)
|
||||
self.return_type = return_type
|
||||
self.return_name = Name(return_name)
|
||||
self.params = params # list of (type, name) pairs
|
||||
self.rustCode = rustCode
|
||||
self.verification = verification
|
||||
self.runtime_error = runtime_error
|
||||
self.unused_self = unused_self
|
||||
self.return_size_increment = return_size_increment
|
||||
|
||||
class ClassDescriptor:
|
||||
|
||||
def __init__(self, class_name, dir_name, rust_class_name, class_len_int, check_valid_contents=True, no_class=False, no_serialize=False,
|
||||
runtime_error_on_serialize=False, string_contents=False, wrap_class=None):
|
||||
self.class_name = Name(class_name)
|
||||
self.class_len = class_name.upper() + "_LEN" # length in bytes
|
||||
self.static_methods = [] # list of StaticMethodDescriptor
|
||||
self.methods = [] # list of MethodDescriptor,
|
||||
self.dir_name = Name(dir_name)
|
||||
self.rust_class_name = rust_class_name
|
||||
self.class_len_int = class_len_int
|
||||
if check_valid_contents and wrap_class == None:
|
||||
self.add_method("check_valid_contents", "boolean", "None", [], "", unused_self=True);
|
||||
self.check_valid_contents = True
|
||||
else:
|
||||
self.check_valid_contents = False
|
||||
self.no_class = no_class
|
||||
self.no_serialize = no_serialize
|
||||
self.runtime_error_on_serialize = runtime_error_on_serialize
|
||||
self.string_contents = string_contents
|
||||
if wrap_class != None:
|
||||
self.wrap_class = Name(wrap_class)
|
||||
else:
|
||||
self.wrap_class = None
|
||||
|
||||
def add_static_method(self, method_name, return_type, return_name, params, rustCode="", verification=False, runtime_error=False,
|
||||
return_size_increment=0):
|
||||
params2 = [(p[0], Name(p[1])) for p in params]
|
||||
self.static_methods.append(StaticMethodDescriptor(method_name, return_type, return_name, params2, rustCode, verification, runtime_error,
|
||||
return_size_increment))
|
||||
|
||||
def add_method(self, method_name, return_type, return_name, params, rustCode="", verification=False, runtime_error=False,
|
||||
return_size_increment=0, unused_self=False):
|
||||
params2 = [(p[0], Name(p[1])) for p in params]
|
||||
self.methods.append(MethodDescriptor(method_name, return_type, return_name, params2, rustCode, verification, runtime_error,
|
||||
unused_self, return_size_increment))
|
||||
|
||||
def define_classes():
|
||||
classes = []
|
||||
|
||||
c = ClassDescriptor("group_identifier", "groups", "simple_types::GroupIdentifierBytes", 32, check_valid_contents=False)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_version", "profiles", "api::profiles::ProfileKeyVersion", 64, check_valid_contents=False, string_contents=True)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("notary_signature", "", "simple_types::NotarySignatureBytes", 64, check_valid_contents=False)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_serial", "receipts", "simple_types::ReceiptSerialBytes", 16, check_valid_contents=False)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key", "profiles", "api::profiles::ProfileKey", 32, check_valid_contents=False)
|
||||
c.add_method("get_commitment", "class", "profile_key_commitment", [("UUID", "uuid")],
|
||||
""" let profile_key_commitment = profile_key.get_commitment(uuid);""");
|
||||
c.add_method("get_profile_key_version", "class", "profile_key_version", [("UUID", "uuid")],
|
||||
""" let profile_key_version = profile_key.get_profile_key_version(uuid);""")
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_commitment", "profiles", "api::profiles::ProfileKeyCommitment", 97)
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("group_master_key", "groups", "api::groups::GroupMasterKey", 32, check_valid_contents=False)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("group_secret_params", "groups", "api::groups::GroupSecretParams", 289, runtime_error_on_serialize=True)
|
||||
|
||||
c.add_static_method("generate_deterministic", "class", "group_secret_params", [("class", "randomness")],
|
||||
""" let group_secret_params = api::groups::GroupSecretParams::generate(randomness);""" )
|
||||
|
||||
c.add_static_method("derive_from_master_key", "class", "group_secret_params", [("class", "group_master_key")],
|
||||
""" let group_secret_params = api::groups::GroupSecretParams::derive_from_master_key(group_master_key);""", runtime_error=True)
|
||||
|
||||
c.add_method("get_master_key", "class", "group_master_key", [],
|
||||
""" let group_master_key = group_secret_params.get_master_key();""")
|
||||
|
||||
c.add_method("get_public_params", "class", "group_public_params", [],
|
||||
""" let group_public_params = group_secret_params.get_public_params();""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("client_zk_group_cipher", "groups", "api::groups::ClientZkGroupCipher", 192, wrap_class="group_secret_params")
|
||||
|
||||
c.add_method("encrypt_uuid", "class", "uuid_ciphertext", [("UUID", "uuid")],
|
||||
""" let uuid_ciphertext = group_secret_params.encrypt_uuid(uuid);""", runtime_error=True)
|
||||
|
||||
c.add_method("decrypt_uuid", "UUID", "uuid", [("class", "uuid_ciphertext")],
|
||||
""" let uuid = match group_secret_params.decrypt_uuid(uuid_ciphertext) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("encrypt_profile_key", "class", "profile_key_ciphertext", [("class", "profile_key"), ("UUID", "uuid")],
|
||||
""" let profile_key_ciphertext = group_secret_params.encrypt_profile_key(profile_key, uuid);""", runtime_error=True)
|
||||
|
||||
c.add_method("decrypt_profile_key", "class", "profile_key", [("class", "profile_key_ciphertext"), ("UUID", "uuid")],
|
||||
""" let profile_key = match group_secret_params.decrypt_profile_key(profile_key_ciphertext, uuid) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("encrypt_blob_deterministic", "byte[]", "blob_ciphertext", [("class", "randomness"), ("byte[]", "plaintext")],
|
||||
""" let blob_ciphertext = match group_secret_params.encrypt_blob(randomness, plaintext) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""", return_size_increment=+29)
|
||||
|
||||
c.add_method("decrypt_blob", "byte[]", "plaintext", [("byte[]", "blob_ciphertext")],
|
||||
""" let plaintext = match group_secret_params.decrypt_blob(blob_ciphertext) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""", return_size_increment=-29)
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("server_secret_params", "", "api::ServerSecretParams", 1121, runtime_error_on_serialize=True)
|
||||
c.add_static_method("generate_deterministic", "class", "server_secret_params", [("class", "randomness")],
|
||||
""" let server_secret_params = api::ServerSecretParams::generate(randomness);""")
|
||||
|
||||
c.add_method("get_public_params", "class", "server_public_params", [],
|
||||
""" let server_public_params = server_secret_params.get_public_params();""")
|
||||
|
||||
c.add_method("sign_deterministic", "class", "notary_signature", [("class", "randomness"), ("byte[]", "message") ],
|
||||
""" let notary_signature = match server_secret_params.sign(randomness, message) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""", runtime_error=True)
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("client_zk_auth_operations", "auth", "api::auth::ClientZkAuthOperations", 256, wrap_class="server_public_params")
|
||||
|
||||
c.add_method("receive_auth_credential", "class", "auth_credential", [("UUID", "uuid"), ("int", "redemption_time"), ("class", "auth_credential_response")],
|
||||
""" let auth_credential = match server_public_params.receive_auth_credential(uuid, redemption_time, &auth_credential_response) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("create_auth_credential_presentation_deterministic", "class", "auth_credential_presentation", [("class", "randomness"), ("class", "group_secret_params"), ("class", "auth_credential")],
|
||||
""" let auth_credential_presentation = server_public_params.create_auth_credential_presentation(randomness, group_secret_params, auth_credential);""", runtime_error=True)
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("client_zk_profile_operations", "profiles", "api::profiles::ClientZkProfileOperations", 256, wrap_class="server_public_params")
|
||||
|
||||
c.add_method("create_profile_key_credential_request_context_deterministic", "class", "profile_key_credential_request_context", [("class", "randomness"), ("UUID", "uuid"), ("class", "profile_key")],
|
||||
""" let profile_key_credential_request_context = server_public_params.create_profile_key_credential_request_context(randomness, uuid, profile_key);""", runtime_error=True)
|
||||
|
||||
c.add_method("receive_profile_key_credential", "class", "profile_key_credential", [("class", "profile_key_credential_request_context"), ("class", "profile_key_credential_response")],
|
||||
""" let profile_key_credential = match server_public_params.receive_profile_key_credential(&profile_key_credential_request_context, &profile_key_credential_response) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("create_profile_key_credential_presentation_deterministic", "class", "profile_key_credential_presentation", [("class", "randomness"), ("class", "group_secret_params"), ("class", "profile_key_credential") ],
|
||||
""" let profile_key_credential_presentation = server_public_params.create_profile_key_credential_presentation(randomness, group_secret_params, profile_key_credential);""", runtime_error=True)
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("client_zk_receipt_operations", "receipts", "api::receipts::ClientZkReceiptOperations", 256, wrap_class="server_public_params")
|
||||
|
||||
c.add_method("create_receipt_credential_request_context_deterministic", "class", "receipt_credential_request_context", [("class", "randomness"), ("class", "receipt_serial")],
|
||||
""" let receipt_credential_request_context = server_public_params.create_receipt_credential_request_context(randomness, receipt_serial);""")
|
||||
|
||||
c.add_method("receive_receipt_credential", "class", "receipt_credential", [("class", "receipt_credential_request_context"), ("class", "receipt_credential_response")],
|
||||
""" let receipt_credential = match server_public_params.receive_receipt_credential(&receipt_credential_request_context, &receipt_credential_response) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("create_receipt_credential_presentation_deterministic", "class", "receipt_credential_presentation", [("class", "randomness"), ("class", "receipt_credential")],
|
||||
""" let receipt_credential_presentation = server_public_params.create_receipt_credential_presentation(randomness, &receipt_credential);""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("server_zk_auth_operations", "auth", "api::auth::ServerZkAuthOperations", 544, wrap_class="server_secret_params")
|
||||
|
||||
c.add_method("issue_auth_credential_deterministic", "class", "auth_credential_response", [("class", "randomness"), ("UUID", "uuid"), ("int", "redemption_time")],
|
||||
""" let auth_credential_response = server_secret_params.issue_auth_credential(randomness, uuid, redemption_time);""", runtime_error=True)
|
||||
|
||||
c.add_method("verify_auth_credential_presentation", "boolean", "None", [("class", "group_public_params"), ("class", "auth_credential_presentation") ],
|
||||
""" match server_secret_params.verify_auth_credential_presentation(group_public_params, &auth_credential_presentation) {
|
||||
Ok(_) => (),
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
}""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("server_zk_profile_operations", "profiles", "api::profiles::ServerZkProfileOperations", 544, wrap_class="server_secret_params")
|
||||
|
||||
c.add_method("issue_profile_key_credential_deterministic", "class", "profile_key_credential_response", [("class", "randomness"), ("class", "profile_key_credential_request"), ("UUID", "uuid"), ("class", "profile_key_commitment")],
|
||||
""" let profile_key_credential_response = match server_secret_params.issue_profile_key_credential(
|
||||
randomness,
|
||||
&profile_key_credential_request,
|
||||
uuid,
|
||||
profile_key_commitment,
|
||||
) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
c.add_method("verify_profile_key_credential_presentation", "boolean", "None", [("class", "group_public_params"), ("class", "profile_key_credential_presentation") ],
|
||||
""" match server_secret_params.verify_profile_key_credential_presentation(group_public_params, &profile_key_credential_presentation) {
|
||||
Ok(_) => (),
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
}""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("server_zk_receipt_operations", "receipts", "api::receipts::ServerZkReceiptOperations", 544, wrap_class="server_secret_params")
|
||||
|
||||
c.add_method("issue_receipt_credential_deterministic", "class", "receipt_credential_response", [("class", "randomness"), ("class", "receipt_credential_request"), ("long", "receipt_expiration_time"), ("long", "receipt_level")],
|
||||
""" let receipt_credential_response = server_secret_params.issue_receipt_credential(
|
||||
randomness,
|
||||
&receipt_credential_request,
|
||||
receipt_expiration_time,
|
||||
receipt_level,
|
||||
);""")
|
||||
|
||||
c.add_method("verify_receipt_credential_presentation", "boolean", "None", [("class", "receipt_credential_presentation")],
|
||||
""" match server_secret_params.verify_receipt_credential_presentation(&receipt_credential_presentation) {
|
||||
Ok(_) => (),
|
||||
Err(_) => return FFI_RETURN_INPUT_ERROR,
|
||||
}""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("group_public_params", "groups", "api::groups::GroupPublicParams", 97)
|
||||
c.add_method("get_group_identifier", "class", "group_identifier", [],
|
||||
""" let group_identifier = group_public_params.get_group_identifier();""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("server_public_params", "", "api::ServerPublicParams", 225, runtime_error_on_serialize=True)
|
||||
|
||||
c.add_method("verify_signature", "boolean", "None", [("byte[]", "message"), ("class", "notary_signature")],
|
||||
""" match server_public_params.verify_signature(message, notary_signature) {
|
||||
Ok(_) => (),
|
||||
_ => return FFI_RETURN_INPUT_ERROR,
|
||||
};""")
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("auth_credential_response", "auth", "api::auth::AuthCredentialResponse", 361)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("auth_credential", "auth", "api::auth::AuthCredential", 181)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("auth_credential_presentation", "auth", "api::auth::AuthCredentialPresentation", 493)
|
||||
c.add_method("get_uuid_ciphertext", "class", "uuid_ciphertext", [],
|
||||
""" let uuid_ciphertext = auth_credential_presentation.get_uuid_ciphertext();""");
|
||||
c.add_method("get_redemption_time", "int", "redemption_time", [],
|
||||
""" let redemption_time = auth_credential_presentation.get_redemption_time();""");
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_credential_request_context", "profiles", "api::profiles::ProfileKeyCredentialRequestContext", 473)
|
||||
c.add_method("get_request", "class", "profile_key_credential_request", [],
|
||||
""" let profile_key_credential_request = profile_key_credential_request_context.get_request();""" )
|
||||
|
||||
classes.append(c)
|
||||
c = ClassDescriptor("profile_key_credential_request", "profiles", "api::profiles::ProfileKeyCredentialRequest", 329)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_credential_response", "profiles", "api::profiles::ProfileKeyCredentialResponse", 457)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_credential", "profiles", "api::profiles::ProfileKeyCredential", 145)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_credential_presentation", "profiles", "api::profiles::ProfileKeyCredentialPresentation", 713)
|
||||
c.add_method("get_uuid_ciphertext", "class", "uuid_ciphertext", [],
|
||||
""" let uuid_ciphertext = profile_key_credential_presentation.get_uuid_ciphertext();""");
|
||||
c.add_method("get_profile_key_ciphertext", "class", "profile_key_ciphertext", [],
|
||||
""" let profile_key_ciphertext = profile_key_credential_presentation.get_profile_key_ciphertext();""");
|
||||
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_credential_request_context", "receipts", "api::receipts::ReceiptCredentialRequestContext", 177)
|
||||
c.add_method("get_request", "class", "receipt_credential_request", [],
|
||||
""" let receipt_credential_request = receipt_credential_request_context.get_request();""")
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_credential_request", "receipts", "api::receipts::ReceiptCredentialRequest", 97)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_credential_response", "receipts", "api::receipts::ReceiptCredentialResponse", 409)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_credential", "receipts", "api::receipts::ReceiptCredential", 129)
|
||||
c.add_method("get_receipt_expiration_time", "long", "receipt_expiration_time", [],
|
||||
""" let receipt_expiration_time = receipt_credential.get_receipt_expiration_time();""")
|
||||
c.add_method("get_receipt_level", "long", "receipt_level", [],
|
||||
""" let receipt_level = receipt_credential.get_receipt_level();""")
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("receipt_credential_presentation", "receipts", "api::receipts::ReceiptCredentialPresentation", 329)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("uuid_ciphertext", "groups", "api::groups::UuidCiphertext", 65)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("profile_key_ciphertext", "groups", "api::groups::ProfileKeyCiphertext", 65)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("randomness", "", "simple_types::RandomnessBytes", 32, no_class=True)
|
||||
classes.append(c)
|
||||
|
||||
c = ClassDescriptor("uuid", "", "simple_types::UidBytes", 32, no_class=True)
|
||||
classes.append(c)
|
||||
|
||||
return classes
|
||||
|
||||
|
||||
|
||||
classes = define_classes()
|
||||
codegen_java.produce_output(classes)
|
||||
codegen_ffiapi.produce_output(classes)
|
||||
codegen_ffiapijava.produce_output(classes)
|
||||
codegen_simpleapi.produce_output(classes)
|
||||
codegen_swift.produce_output(classes)
|
||||
@ -1,126 +0,0 @@
|
||||
|
||||
file_header = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use super::simpleapi;
|
||||
use std::{panic, slice};
|
||||
use crate::ffi::constants::FFI_RETURN_INTERNAL_ERROR;
|
||||
"""
|
||||
|
||||
template_method_start = \
|
||||
"""
|
||||
#[no_mangle]
|
||||
pub extern "C" fn %(function_name)s(
|
||||
"""
|
||||
|
||||
template_method_decl_end = \
|
||||
""") -> i32 {
|
||||
"""
|
||||
|
||||
template_method_body_start = \
|
||||
""" let result = panic::catch_unwind(|| {
|
||||
"""
|
||||
|
||||
template_method_body_end = \
|
||||
"""
|
||||
match result {
|
||||
Ok(result) => result,
|
||||
Err(_) => FFI_RETURN_INTERNAL_ERROR,
|
||||
}
|
||||
"""
|
||||
|
||||
def get_args(params, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
s += param[1].snake() + ", "
|
||||
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
|
||||
def print_method(c, m, static):
|
||||
s = ""
|
||||
|
||||
if c.wrap_class == None:
|
||||
class_name = c.class_name
|
||||
else:
|
||||
class_name = c.wrap_class
|
||||
|
||||
function_name = "FFI_" + class_name.camel() + "_" + m.method_name.lower_camel()
|
||||
s += template_method_start % {"function_name": function_name}
|
||||
|
||||
# decl
|
||||
if not static:
|
||||
s += " " + class_name.lower_camel() + ": *const u8,\n"
|
||||
s += " " + class_name.lower_camel() + "Len: u32,\n"
|
||||
for param in m.params:
|
||||
if param[0] == "int":
|
||||
s += f" {param[1].lower_camel()}: u32,\n"
|
||||
elif param[0] == "long":
|
||||
s += f" {param[1].lower_camel()}: u64,\n"
|
||||
else:
|
||||
s += f" {param[1].lower_camel()}: *const u8,\n"
|
||||
s += f" {param[1].lower_camel()}Len: u32,\n"
|
||||
if m.return_type != "boolean":
|
||||
s += " " + m.return_name.lower_camel() + "Out: *mut u8,\n"
|
||||
s += " " + m.return_name.lower_camel() + "Len: u32,\n"
|
||||
s += template_method_decl_end
|
||||
|
||||
# body
|
||||
s += template_method_body_start
|
||||
|
||||
if not static:
|
||||
s += " let " + class_name.snake() + ": &[u8] = unsafe { slice::from_raw_parts(%s, %sLen as usize) };\n" % (class_name.lower_camel(), class_name.lower_camel())
|
||||
for param in m.params:
|
||||
if param[0] == "int":
|
||||
s += f" let {param[1].snake()} = {param[1].lower_camel()} as u32;\n"
|
||||
elif param[0] == "long":
|
||||
s += f" let {param[1].snake()} = {param[1].lower_camel()} as u64;\n"
|
||||
else:
|
||||
s += f" let {param[1].snake()}: &[u8] = unsafe {{ slice::from_raw_parts({param[1].lower_camel()}, {param[1].lower_camel()}Len as usize) }};\n"
|
||||
if m.return_type != "boolean":
|
||||
s += " let %s: &mut [u8] = unsafe { slice::from_raw_parts_mut(%sOut, %sLen as usize) };\n" % (m.return_name.snake(), m.return_name.lower_camel(), m.return_name.lower_camel())
|
||||
|
||||
if not static:
|
||||
if m.return_type != "boolean":
|
||||
s += """\n simpleapi::%s_%s(%s, %s %s)\n""" % (class_name.camel(), m.method_name.lower_camel(), class_name.snake(), get_args(m.params, True), m.return_name.snake())
|
||||
else:
|
||||
s += """\n simpleapi::%s_%s(%s, %s)\n""" % (class_name.camel(), m.method_name.lower_camel(), class_name.snake(), get_args(m.params, False))
|
||||
else:
|
||||
if m.return_type != "boolean":
|
||||
s += """\n simpleapi::%s_%s(%s %s)\n""" % (class_name.camel(), m.method_name.lower_camel(), get_args(m.params, True), m.return_name.snake())
|
||||
else:
|
||||
s += """\n simpleapi::%s_%s(%s)\n""" % (class_name.camel(), m.method_name.lower_camel(), get_args(m.params, False))
|
||||
s += " });\n"
|
||||
|
||||
s += template_method_body_end
|
||||
s += "}\n"
|
||||
|
||||
return s
|
||||
|
||||
def print_class(c):
|
||||
s = ""
|
||||
for method in c.static_methods:
|
||||
s += print_method(c, method, True)
|
||||
for method in c.methods:
|
||||
s += print_method(c, method, False)
|
||||
return s
|
||||
|
||||
|
||||
def produce_output(classes):
|
||||
s = file_header
|
||||
for c in classes:
|
||||
s += print_class(c)
|
||||
f = open("ffiapi/ffiapi.rs", "w")
|
||||
f.write(s)
|
||||
f.close()
|
||||
@ -1,167 +0,0 @@
|
||||
|
||||
file_header = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::panic;
|
||||
|
||||
use crate::ffi::constants::*;
|
||||
|
||||
extern crate jni;
|
||||
|
||||
use super::simpleapi;
|
||||
|
||||
use jni::sys::jint;
|
||||
use jni::sys::jlong;
|
||||
|
||||
// This is the interface to the JVM that we'll
|
||||
// call the majority of our methods on.
|
||||
use jni::JNIEnv;
|
||||
|
||||
// These objects are what you should use as arguments to your native function.
|
||||
// They carry extra lifetime information to prevent them escaping this context
|
||||
// and getting used after being GC'd.
|
||||
use jni::objects::JClass;
|
||||
|
||||
// This is just a pointer. We'll be returning it from our function.
|
||||
// We can't return one of the objects with lifetime information because the
|
||||
// lifetime checker won't let us.
|
||||
use jni::sys::jbyteArray;
|
||||
|
||||
fn u8toi8(input: Vec<u8>) -> Vec<i8> {
|
||||
let mut out: Vec<i8> = Default::default();
|
||||
for &i in &input {
|
||||
out.push(i as i8);
|
||||
}
|
||||
out
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_start = \
|
||||
"""
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_signal_zkgroup_internal_Native_%(function_name)sJNI(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
"""
|
||||
|
||||
template_method_decl_end = \
|
||||
""") -> i32 {
|
||||
"""
|
||||
|
||||
template_method_body_start = \
|
||||
""" let result = panic::catch_unwind(|| {
|
||||
"""
|
||||
|
||||
template_method_body_end = \
|
||||
"""
|
||||
match result {
|
||||
Ok(result) => result,
|
||||
Err(_) => FFI_RETURN_INTERNAL_ERROR,
|
||||
}
|
||||
"""
|
||||
|
||||
def get_args(params, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[0] == "int" or param[0] == "long":
|
||||
s += param[1].snake() + ", "
|
||||
else:
|
||||
s += "&" + param[1].snake() + ", "
|
||||
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
|
||||
def print_method(c, m, static):
|
||||
s = ""
|
||||
|
||||
if c.wrap_class == None:
|
||||
class_name = c.class_name
|
||||
else:
|
||||
class_name = c.wrap_class
|
||||
|
||||
function_name = class_name.lower_camel() + m.method_name.camel()
|
||||
s += template_method_start % {"function_name": function_name}
|
||||
|
||||
# decl
|
||||
if not static:
|
||||
s += " " + class_name.lower_camel() + ": jbyteArray,\n"
|
||||
for param in m.params:
|
||||
if param[0] == "int":
|
||||
s += f" {param[1].lower_camel()}: jint,\n"
|
||||
elif param[0] == "long":
|
||||
s += f" {param[1].lower_camel()}: jlong,\n"
|
||||
else:
|
||||
s += f" {param[1].lower_camel()}: jbyteArray,\n"
|
||||
if m.return_type != "boolean":
|
||||
s += " " + m.return_name.lower_camel() + "Out: jbyteArray,\n"
|
||||
s += template_method_decl_end
|
||||
|
||||
# body
|
||||
s += template_method_body_start
|
||||
|
||||
if not static:
|
||||
s += " let " + class_name.snake() + " = env.convert_byte_array(%s).unwrap();\n" % class_name.lower_camel()
|
||||
for param in m.params:
|
||||
if param[0] == "int":
|
||||
s += f" let {param[1].snake()} = {param[1].lower_camel()} as u32;\n"
|
||||
elif param[0] == "long":
|
||||
s += f" let {param[1].snake()} = {param[1].lower_camel()} as u64;\n"
|
||||
else:
|
||||
s += f" let {param[1].snake()} = env.convert_byte_array({param[1].lower_camel()}).unwrap();\n"
|
||||
if m.return_type != "boolean":
|
||||
s += " let mut %s: Vec<u8> = vec![0; env.get_array_length(%sOut).unwrap() as usize];\n" % (m.return_name.snake(), m.return_name.lower_camel())
|
||||
|
||||
if not static:
|
||||
if m.return_type != "boolean":
|
||||
s += """\n let ffi_return = simpleapi::%s_%s(&%s, %s &mut %s);\n""" % (class_name.camel(), m.method_name.lower_camel(), class_name.snake(), get_args(m.params, True), m.return_name.snake())
|
||||
else:
|
||||
s += """\n let ffi_return = simpleapi::%s_%s(&%s, %s);\n""" % (class_name.camel(), m.method_name.lower_camel(), class_name.snake(), get_args(m.params, False))
|
||||
else:
|
||||
if m.return_type != "boolean":
|
||||
s += """\n let ffi_return = simpleapi::%s_%s(%s &mut %s);\n""" % (class_name.camel(), m.method_name.lower_camel(), get_args(m.params, True), m.return_name.snake())
|
||||
else:
|
||||
s += """\n let ffi_return = simpleapi::%s_%s(%s);\n""" % (class_name.camel(), m.method_name.lower_camel(), get_args(m.params, False))
|
||||
|
||||
s += """ if ffi_return != FFI_RETURN_OK {
|
||||
return ffi_return;\n }\n"""
|
||||
|
||||
if m.return_type != "boolean":
|
||||
s += "\n env.set_byte_array_region(%sOut, 0, &u8toi8(%s)[..]).unwrap();\n FFI_RETURN_OK\n" % \
|
||||
(m.return_name.lower_camel(), m.return_name.snake())
|
||||
else:
|
||||
s += " FFI_RETURN_OK\n"
|
||||
|
||||
s += " });\n"
|
||||
|
||||
s += template_method_body_end
|
||||
s += "}\n"
|
||||
|
||||
return s
|
||||
|
||||
def print_class(c):
|
||||
s = ""
|
||||
for method in c.static_methods:
|
||||
s += print_method(c, method, True)
|
||||
for method in c.methods:
|
||||
s += print_method(c, method, False)
|
||||
return s
|
||||
|
||||
|
||||
def produce_output(classes):
|
||||
s = file_header
|
||||
for c in classes:
|
||||
s += print_class(c)
|
||||
f = open("ffiapijava/ffiapijava.rs", "w")
|
||||
f.write(s)
|
||||
f.close()
|
||||
@ -1,200 +0,0 @@
|
||||
diff --git b/ffi/java/src/main/java/org/signal/zkgroup/auth/ServerZkAuthOperations.java a/ffi/java/src/main/java/org/signal/zkgroup/auth/ServerZkAuthOperations.java
|
||||
index a2567a55ef32..57d99c13ed71 100644
|
||||
--- b/ffi/java/src/main/java/org/signal/zkgroup/auth/ServerZkAuthOperations.java
|
||||
+++ a/ffi/java/src/main/java/org/signal/zkgroup/auth/ServerZkAuthOperations.java
|
||||
@@ -11,9 +11,11 @@ package org.signal.zkgroup.auth;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerSecretParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
+import org.signal.zkgroup.InvalidRedemptionTimeException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.GroupPublicParams;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
@@ -51,7 +53,18 @@ public class ServerZkAuthOperations {
|
||||
|
||||
}
|
||||
|
||||
- public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation) throws VerificationFailedException {
|
||||
+ public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation) throws VerificationFailedException, InvalidRedemptionTimeException {
|
||||
+ verifyAuthCredentialPresentation(groupPublicParams, authCredentialPresentation, System.currentTimeMillis());
|
||||
+ }
|
||||
+
|
||||
+ public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation, long currentTimeMillis) throws VerificationFailedException, InvalidRedemptionTimeException {
|
||||
+ long acceptableStartTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()-1, TimeUnit.DAYS);
|
||||
+ long acceptableEndTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()+2, TimeUnit.DAYS);
|
||||
+
|
||||
+ if (currentTimeMillis < acceptableStartTime || currentTimeMillis > acceptableEndTime) {
|
||||
+ throw new InvalidRedemptionTimeException();
|
||||
+ }
|
||||
+
|
||||
int ffi_return = Native.serverSecretParamsVerifyAuthCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), authCredentialPresentation.getInternalContentsForJNI());
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
diff --git b/ffi/java/src/main/java/org/signal/zkgroup/groups/ClientZkGroupCipher.java a/ffi/java/src/main/java/org/signal/zkgroup/groups/ClientZkGroupCipher.java
|
||||
index 464cf6d19ecc..5739505935b0 100644
|
||||
--- b/ffi/java/src/main/java/org/signal/zkgroup/groups/ClientZkGroupCipher.java
|
||||
+++ a/ffi/java/src/main/java/org/signal/zkgroup/groups/ClientZkGroupCipher.java
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
+import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
@@ -100,12 +101,16 @@ public class ClientZkGroupCipher {
|
||||
}
|
||||
|
||||
public byte[] encryptBlob(SecureRandom secureRandom, byte[] plaintext) throws VerificationFailedException {
|
||||
- byte[] newContents = new byte[plaintext.length+29];
|
||||
+
|
||||
+ byte[] paddedPlaintext = new byte[plaintext.length + 4];
|
||||
+ System.arraycopy(plaintext, 0, paddedPlaintext, 4, plaintext.length);
|
||||
+
|
||||
+ byte[] newContents = new byte[paddedPlaintext.length+29];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
- int ffi_return = Native.groupSecretParamsEncryptBlobDeterministicJNI(groupSecretParams.getInternalContentsForJNI(), random, plaintext, newContents);
|
||||
+ int ffi_return = Native.groupSecretParamsEncryptBlobDeterministicJNI(groupSecretParams.getInternalContentsForJNI(), random, paddedPlaintext, newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
@@ -129,7 +134,21 @@ public class ClientZkGroupCipher {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
- return newContents;
|
||||
+ if (newContents.length < 4) {
|
||||
+ throw new VerificationFailedException();
|
||||
+ }
|
||||
+
|
||||
+ byte[] padLenBytes = new byte[4];
|
||||
+ System.arraycopy(newContents, 0, padLenBytes, 0, 4);
|
||||
+ int padLen = ByteBuffer.wrap(newContents).getInt();
|
||||
+ if (newContents.length < (4 + padLen)) {
|
||||
+ throw new VerificationFailedException();
|
||||
+ }
|
||||
+
|
||||
+ byte[] depaddedContents = new byte[newContents.length - (4 + padLen)];
|
||||
+ System.arraycopy(newContents, 4, depaddedContents, 0, newContents.length - (4 + padLen));
|
||||
+
|
||||
+ return depaddedContents;
|
||||
}
|
||||
|
||||
}
|
||||
diff --git b/ffi/java/src/main/java/org/signal/zkgroup/profiles/ClientZkProfileOperations.java a/ffi/java/src/main/java/org/signal/zkgroup/profiles/ClientZkProfileOperations.java
|
||||
index cbc73ac60bee..57a252f5886d 100644
|
||||
--- b/ffi/java/src/main/java/org/signal/zkgroup/profiles/ClientZkProfileOperations.java
|
||||
+++ a/ffi/java/src/main/java/org/signal/zkgroup/profiles/ClientZkProfileOperations.java
|
||||
@@ -52,6 +52,10 @@ public class ClientZkProfileOperations {
|
||||
}
|
||||
|
||||
public ProfileKeyCredential receiveProfileKeyCredential(ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext, ProfileKeyCredentialResponse profileKeyCredentialResponse) throws VerificationFailedException {
|
||||
+ if (profileKeyCredentialResponse == null) {
|
||||
+ throw new VerificationFailedException();
|
||||
+ }
|
||||
+
|
||||
byte[] newContents = new byte[ProfileKeyCredential.SIZE];
|
||||
|
||||
int ffi_return = Native.serverPublicParamsReceiveProfileKeyCredentialJNI(serverPublicParams.getInternalContentsForJNI(), profileKeyCredentialRequestContext.getInternalContentsForJNI(), profileKeyCredentialResponse.getInternalContentsForJNI(), newContents);
|
||||
diff --git b/ffi/java/src/main/java/org/signal/zkgroup/profiles/ProfileKey.java a/ffi/java/src/main/java/org/signal/zkgroup/profiles/ProfileKey.java
|
||||
index 2251da362b0e..9170b5fd9a5c 100644
|
||||
--- b/ffi/java/src/main/java/org/signal/zkgroup/profiles/ProfileKey.java
|
||||
+++ a/ffi/java/src/main/java/org/signal/zkgroup/profiles/ProfileKey.java
|
||||
@@ -25,14 +25,10 @@ public final class ProfileKey extends ByteArray {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
- public ProfileKeyCommitment getCommitment(UUID uuid) throws VerificationFailedException {
|
||||
+ public ProfileKeyCommitment getCommitment(UUID uuid) {
|
||||
byte[] newContents = new byte[ProfileKeyCommitment.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyGetCommitmentJNI(contents, UUIDUtil.serialize(uuid), newContents);
|
||||
- if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
- throw new VerificationFailedException();
|
||||
- }
|
||||
-
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
@@ -45,14 +41,10 @@ public final class ProfileKey extends ByteArray {
|
||||
|
||||
}
|
||||
|
||||
- public ProfileKeyVersion getProfileKeyVersion(UUID uuid) throws VerificationFailedException {
|
||||
+ public ProfileKeyVersion getProfileKeyVersion(UUID uuid) {
|
||||
byte[] newContents = new byte[ProfileKeyVersion.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyGetProfileKeyVersionJNI(contents, UUIDUtil.serialize(uuid), newContents);
|
||||
- if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
- throw new VerificationFailedException();
|
||||
- }
|
||||
-
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
diff --git b/ffi/swift/Sources/ZKGroup/ClientZkGroupCipher.swift a/ffi/swift/Sources/ZKGroup/ClientZkGroupCipher.swift
|
||||
index 4d36edb46acf..fa7f1b4aba5c 100644
|
||||
--- b/ffi/swift/Sources/ZKGroup/ClientZkGroupCipher.swift
|
||||
+++ a/ffi/swift/Sources/ZKGroup/ClientZkGroupCipher.swift
|
||||
@@ -91,7 +91,7 @@ public class ClientZkGroupCipher {
|
||||
|
||||
}
|
||||
|
||||
- public func encryptBlob(plaintext: [UInt8]) throws -> BlobCiphertext {
|
||||
+ public func encryptBlob(plaintext: [UInt8]) throws -> [UInt8] {
|
||||
var randomness: [UInt8] = Array(repeating: 0, count: Int(32))
|
||||
let result = SecRandomCopyBytes(kSecRandomDefault, randomness.count, &randomness)
|
||||
guard result == errSecSuccess else {
|
||||
@@ -102,9 +102,11 @@ public class ClientZkGroupCipher {
|
||||
}
|
||||
|
||||
public func encryptBlob(randomness: [UInt8], plaintext: [UInt8]) throws -> [UInt8] {
|
||||
- var newContents: [UInt8] = Array(repeating: 0, count: Int(randomness.count+29))
|
||||
+ let paddedPlaintext = Array(repeating:0, count: 4) + plaintext
|
||||
|
||||
- let ffi_return = FFI_GroupSecretParams_encryptBlobDeterministic(groupSecretParams.getInternalContentsForFFI(), UInt32(groupSecretParams.getInternalContentsForFFI().count), randomness, UInt32(randomness.count), plaintext, UInt32(plaintext.count), &newContents, UInt32(newContents.count))
|
||||
+ var newContents: [UInt8] = Array(repeating: 0, count: Int(paddedPlaintext.count+29))
|
||||
+
|
||||
+ let ffi_return = FFI_GroupSecretParams_encryptBlobDeterministic(groupSecretParams.getInternalContentsForFFI(), UInt32(groupSecretParams.getInternalContentsForFFI().count), randomness, UInt32(randomness.count), paddedPlaintext, UInt32(paddedPlaintext.count), &newContents, UInt32(newContents.count))
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}
|
||||
@@ -117,9 +120,10 @@ public class ClientZkGroupCipher {
|
||||
}
|
||||
|
||||
public func decryptBlob(blobCiphertext: [UInt8]) throws -> [UInt8] {
|
||||
- var newContents: [UInt8] = Array(repeating: 0, count: Int(blobCiphertext.count+-29))
|
||||
+ var newContents: [UInt8] = Array(repeating: 0, count: Int(blobCiphertext.count-29))
|
||||
|
||||
let ffi_return = FFI_GroupSecretParams_decryptBlob(groupSecretParams.getInternalContentsForFFI(), UInt32(groupSecretParams.getInternalContentsForFFI().count), blobCiphertext, UInt32(blobCiphertext.count), &newContents, UInt32(newContents.count))
|
||||
+
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}
|
||||
@@ -128,7 +131,18 @@ public class ClientZkGroupCipher {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
- return newContents
|
||||
+ if newContents.count < 4 {
|
||||
+ throw ZkGroupException.VerificationFailed
|
||||
+ }
|
||||
+
|
||||
+ var paddingLen = newContents.withUnsafeBytes({ $0.load(fromByteOffset:0, as: UInt32.self) })
|
||||
+ paddingLen = UInt32(bigEndian: paddingLen)
|
||||
+
|
||||
+ if (newContents.count < (4 + paddingLen)) {
|
||||
+ throw ZkGroupException.VerificationFailed
|
||||
+ }
|
||||
+
|
||||
+ return Array(newContents[4 ..< newContents.endIndex - Int(paddingLen)])
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,769 +0,0 @@
|
||||
|
||||
template_class = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup%(dir_section)s;
|
||||
|
||||
%(imports)s
|
||||
|
||||
public final class %(class_name)s extends ByteArray {
|
||||
|
||||
public static final int SIZE = %(size)s;
|
||||
%(static_methods)s%(constructors)s
|
||||
%(methods)s%(serialize_method)s}
|
||||
"""
|
||||
|
||||
template_constructor = \
|
||||
"""
|
||||
%(constructor_access)s %(class_name)s(%(constructor_contents_type)s contents) %(constructor_exception_decl)s {
|
||||
super(%(constructor_contents)s, SIZE%(runtime_error_bool)s);%(check_valid_contents)s
|
||||
}
|
||||
"""
|
||||
|
||||
template_constructor_for_string_contents = \
|
||||
"""
|
||||
%(constructor_access)s %(class_name)s(%(constructor_contents_type)s contents) %(constructor_exception_decl)s {
|
||||
super(%(constructor_contents)s, SIZE%(runtime_error_bool)s);%(check_valid_contents)s
|
||||
}
|
||||
"""
|
||||
|
||||
serialize_method_string = \
|
||||
"""
|
||||
public String serialize() {
|
||||
try {
|
||||
return new String(contents, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
serialize_method_binary = \
|
||||
"""
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
template_wrapping_class = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup%(dir_section)s;
|
||||
|
||||
%(imports)s
|
||||
|
||||
public class %(class_name)s {
|
||||
|
||||
private final %(wrapped_class_type)s %(wrapped_class_var)s;
|
||||
%(static_methods)s
|
||||
public %(class_name)s(%(wrapped_class_type)s %(wrapped_class_var)s) {
|
||||
this.%(wrapped_class_var)s = %(wrapped_class_var)s;
|
||||
}
|
||||
%(methods)s
|
||||
}
|
||||
"""
|
||||
|
||||
template_check_valid_contents_constructor = \
|
||||
"""
|
||||
|
||||
int ffi_return = Native.%(class_name_lower_camel)sCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}"""
|
||||
|
||||
template_check_valid_contents_constructor_runtime_error = \
|
||||
"""
|
||||
|
||||
int ffi_return = Native.%(class_name_lower_camel)sCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}"""
|
||||
|
||||
template_static_method = \
|
||||
"""
|
||||
%(access)s static %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_name)s.SIZE];%(get_rand)s
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new %(return_name)s(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_static_method_retval_runtime_error_on_serialize = \
|
||||
"""
|
||||
%(access)s static %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_name)s.SIZE];%(get_rand)s
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new %(return_name)s(newContents);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_static_method_rand_wrapper = \
|
||||
"""
|
||||
%(access)s static %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
return %(full_method_name)s(%(param_args)s);
|
||||
}
|
||||
"""
|
||||
|
||||
template_method = \
|
||||
"""
|
||||
%(access)s %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_len)s];%(get_rand)s
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new %(return_name)s(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_retval_runtime_error_on_serialize = \
|
||||
"""
|
||||
%(access)s %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_len)s];%(get_rand)s
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return new %(return_name)s(newContents);
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_bool = \
|
||||
"""
|
||||
%(access)s void %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)s);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_uuid = \
|
||||
"""
|
||||
%(access)s UUID %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_len)s];
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return UUIDUtil.deserialize(newContents);
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_bytearray = \
|
||||
"""
|
||||
%(access)s byte[] %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[%(return_len)s];%(get_rand)s
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return newContents;
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_int = \
|
||||
"""
|
||||
%(access)s int %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[4];
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return ByteBuffer.wrap(newContents).getInt();
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_long = \
|
||||
"""
|
||||
%(access)s long %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
byte[] newContents = new byte[8];
|
||||
|
||||
int ffi_return = Native.%(jni_method_name)s(%(contents)s, %(param_args)snewContents);%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return ByteBuffer.wrap(newContents).getLong();
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_rand_wrapper = \
|
||||
"""
|
||||
public %(return_name)s %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
return %(full_method_name)s(%(param_args)s);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
template_native = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public final class Native {
|
||||
|
||||
public static final int FFI_RETURN_OK = 0;
|
||||
public static final int FFI_RETURN_INTERNAL_ERROR = 1; // ZkGroupError
|
||||
public static final int FFI_RETURN_INPUT_ERROR = 2;
|
||||
|
||||
public static final int RANDOM_LENGTH = 32;
|
||||
|
||||
static {
|
||||
try {
|
||||
String osName = System.getProperty("os.name").toLowerCase(java.util.Locale.ROOT);
|
||||
boolean isMacOs = osName.startsWith("mac os x");
|
||||
String extension = isMacOs ? ".dylib" : ".so";
|
||||
|
||||
try (InputStream in = Native.class.getResourceAsStream("/libzkgroup" + extension)) {
|
||||
if (in != null) {
|
||||
copyToTempFileAndLoad(in, extension);
|
||||
} else {
|
||||
System.loadLibrary("zkgroup");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Native() {
|
||||
}
|
||||
|
||||
private static void copyToTempFileAndLoad(InputStream in, String extension) throws IOException {
|
||||
File tempFile = Files.createTempFile("resource", extension).toFile();
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
try (OutputStream out = new FileOutputStream(tempFile)) {
|
||||
|
||||
copy(in, out);
|
||||
}
|
||||
System.load(tempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
template_native_end = \
|
||||
"""
|
||||
private static void copy(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
native_string = template_native
|
||||
|
||||
def add_import(import_strings, class_dir_dict, my_dir_name, class_name):
|
||||
dir_name = class_dir_dict[class_name.snake()].snake()
|
||||
if len(dir_name)==0 and len(my_dir_name.snake()) == 0:
|
||||
return
|
||||
elif dir_name == my_dir_name.snake():
|
||||
return
|
||||
if dir_name:
|
||||
import_strings.append("import org.signal.zkgroup.%s.%s;" % (dir_name, class_name.camel()))
|
||||
else:
|
||||
import_strings.append("import org.signal.zkgroup.%s;" % (class_name.camel()))
|
||||
|
||||
def get_decls(params, import_strings, class_dir_dict, my_dir_name):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[1].snake() == "randomness":
|
||||
s += "SecureRandom secureRandom, "
|
||||
import_strings.append("import java.security.SecureRandom;")
|
||||
elif param[0] == "class":
|
||||
s += param[1].camel() + " " + param[1].lower_camel() + ", "
|
||||
add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
else:
|
||||
s += param[0] + " " + param[1].lower_camel() + ", "
|
||||
if len(s) != 0:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def get_rand_wrapper_decls(params):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[1].snake() != "randomness":
|
||||
if param[0] == "class":
|
||||
s += param[1].camel() + " " + param[1].lower_camel() + ", "
|
||||
else:
|
||||
s += param[0] + " " + param[1].lower_camel() + ", "
|
||||
if len(s) != 0:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
|
||||
def get_args(params, import_strings, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[0] == "byte[]" or param[0] == "int" or param[0] == "long":
|
||||
s += param[1].lower_camel() + ", "
|
||||
elif param[0] == "UUID":
|
||||
s += "UUIDUtil.serialize(" + param[1].lower_camel() + "), "
|
||||
import_strings.append("import java.util.UUID;")
|
||||
import_strings.append("import org.signal.zkgroup.util.UUIDUtil;")
|
||||
elif param[1].snake() == "randomness":
|
||||
s += "random, "
|
||||
else:
|
||||
s += param[1].lower_camel() + ".getInternalContentsForJNI(), "
|
||||
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def get_jni_arg_decls(params, selfBool, commaAtEndBool):
|
||||
s = ""
|
||||
if selfBool:
|
||||
s += "byte[] self, "
|
||||
counter = 0
|
||||
for param in params:
|
||||
if param[0] == "int":
|
||||
s += f"int {param[1].lower_camel()}, "
|
||||
elif param[0] == "long":
|
||||
s += f"long {param[1].lower_camel()}, "
|
||||
else:
|
||||
s += f"byte[] {param[1].lower_camel()}, "
|
||||
counter += 1
|
||||
|
||||
if len(s) != 0 and not commaAtEndBool:
|
||||
s = s[:-2]
|
||||
|
||||
if commaAtEndBool:
|
||||
s += "byte[] output"
|
||||
|
||||
return s
|
||||
|
||||
def get_rand_wrapper_args(params, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[0] == "byte[]":
|
||||
s += param[1].lower_camel() + ", "
|
||||
elif param[1].snake() == "randomness":
|
||||
s += "new SecureRandom(), "
|
||||
else:
|
||||
s += param[1].lower_camel() + ", "
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def append_jni_function_decl(jni_method_name, params, selfBool, commaAtEndBool):
|
||||
global native_string
|
||||
native_string += " public static native int " + jni_method_name + "(%s);\n" % get_jni_arg_decls(params, selfBool, commaAtEndBool)
|
||||
|
||||
def append_jni_check_valid_contents(jni_method_name):
|
||||
global native_string
|
||||
native_string += " public static native int " + jni_method_name + "(byte[] self);\n"
|
||||
|
||||
def print_class(c, runtime_error_on_serialize_dict, class_dir_dict):
|
||||
static_methods_string = ""
|
||||
if len(c.methods) == 0 and len(c.static_methods) == 0:
|
||||
import_strings = []
|
||||
else:
|
||||
import_strings = [\
|
||||
"import org.signal.zkgroup.internal.Native;",
|
||||
]
|
||||
|
||||
global native_string
|
||||
my_dir_name = c.dir_name
|
||||
|
||||
if c.wrap_class == None:
|
||||
contents = "contents"
|
||||
else:
|
||||
contents = c.wrap_class.lower_camel() + ".getInternalContentsForJNI()"
|
||||
add_import(import_strings, class_dir_dict, my_dir_name, c.wrap_class)
|
||||
|
||||
for method in c.static_methods:
|
||||
|
||||
exception_decl = ""
|
||||
exception_check =""
|
||||
if len(method.params) > 1 or (len(method.params) == 1 and not method.method_name.snake().endswith("_deterministic")):
|
||||
if method.runtime_error == False:
|
||||
if method.verification == False:
|
||||
if my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.VerificationFailedException;")
|
||||
exception_decl = "throws VerificationFailedException "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}"""
|
||||
else:
|
||||
exception_decl = "throws VerificationFailedException "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_VERIFICATION_FAILED) {
|
||||
throw new VerificationFailedException();
|
||||
}"""
|
||||
|
||||
access = "public"
|
||||
method_name = method.method_name.lower_camel()
|
||||
get_rand = ""
|
||||
if method.method_name.snake().endswith("_deterministic"):
|
||||
import_strings.append("import java.security.SecureRandom;")
|
||||
method_name = method.method_name.lower_camel()[:-len("Deterministic")]
|
||||
param_args = get_rand_wrapper_args(method.params, False)
|
||||
get_rand = """\n byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);"""
|
||||
static_methods_string += template_static_method_rand_wrapper % {
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"full_method_name": method_name,
|
||||
"param_decls": get_rand_wrapper_decls(method.params),
|
||||
"param_args": param_args,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
}
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
if c.wrap_class == None:
|
||||
jni_method_name = c.class_name.lower_camel() + method.method_name.camel() + "JNI"
|
||||
else:
|
||||
jni_method_name = c.wrap_class.lower_camel() + method.method_name.camel() + "JNI"
|
||||
append_jni_function_decl(jni_method_name, method.params, False, True)
|
||||
if runtime_error_on_serialize_dict[method.return_name.snake()]:
|
||||
template = template_static_method_retval_runtime_error_on_serialize
|
||||
import_strings.append("import org.signal.zkgroup.ZkGroupError;")
|
||||
else:
|
||||
template = template_static_method
|
||||
if my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.InvalidInputException;")
|
||||
static_methods_string += template % {
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"return_len": c.class_len,
|
||||
"param_decls": get_decls(method.params, import_strings, class_dir_dict, my_dir_name),
|
||||
"param_args": param_args,
|
||||
"jni_method_name": jni_method_name,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
"get_rand": get_rand,
|
||||
}
|
||||
|
||||
methods_string = ""
|
||||
for method in c.methods:
|
||||
|
||||
if method.method_name.snake() == "check_valid_contents":
|
||||
continue
|
||||
|
||||
exception_decl = ""
|
||||
exception_check =""
|
||||
if len(method.params) != 0:
|
||||
if method.runtime_error == False:
|
||||
if method.verification == False:
|
||||
if my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.VerificationFailedException;")
|
||||
exception_decl = "throws VerificationFailedException "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}"""
|
||||
else:
|
||||
exception_decl = "throws VerificationFailedException "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_VERIFICATION_FAILED) {
|
||||
throw new VerificationFailedException();
|
||||
}"""
|
||||
|
||||
access = "public"
|
||||
method_name = method.method_name.lower_camel()
|
||||
get_rand = ""
|
||||
if method.method_name.snake().endswith("_deterministic"):
|
||||
import_strings.append("import java.security.SecureRandom;")
|
||||
method_name = method.method_name.lower_camel()[:-len("Deterministic")]
|
||||
param_args = get_rand_wrapper_args(method.params, False)
|
||||
get_rand = """\n byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);"""
|
||||
|
||||
# Maybe add more cases to support different return types
|
||||
if method.return_type == "byte[]":
|
||||
return_name = "byte[]"
|
||||
else:
|
||||
return_name = method.return_name.camel()
|
||||
|
||||
methods_string += template_method_rand_wrapper % {
|
||||
"contents": contents,
|
||||
"method_name": method_name,
|
||||
"return_name": return_name,
|
||||
"full_method_name": method_name,
|
||||
"param_decls": get_rand_wrapper_decls(method.params),
|
||||
"param_args": param_args,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
}
|
||||
|
||||
if c.wrap_class == None:
|
||||
jni_method_name = c.class_name.lower_camel() + method.method_name.camel() + "JNI"
|
||||
else:
|
||||
jni_method_name = c.wrap_class.lower_camel() + method.method_name.camel() + "JNI"
|
||||
|
||||
return_len = None
|
||||
if method.return_type == "boolean":
|
||||
template = template_method_bool
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, False)
|
||||
elif method.return_type == "int":
|
||||
template = template_method_int
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, True)
|
||||
import_strings += "import java.nio.ByteBuffer;",
|
||||
elif method.return_type == "long":
|
||||
template = template_method_long
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, True)
|
||||
import_strings += "import java.nio.ByteBuffer;",
|
||||
elif method.return_type == "UUID":
|
||||
import_strings.append("import java.util.UUID;")
|
||||
template = template_method_uuid
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, True)
|
||||
elif method.return_type == "byte[]": # copied from UUID?
|
||||
template = template_method_bytearray
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, True)
|
||||
if method.params[0][1].lower_camel() == "randomness":
|
||||
return_len = method.params[1][1].lower_camel() # hardcode to second arg if first is randomness
|
||||
else:
|
||||
return_len = method.params[0][1].lower_camel() # hardcode to first arg
|
||||
if method.return_size_increment >= 0:
|
||||
return_len += ".length+%d" % method.return_size_increment
|
||||
if method.return_size_increment < 0:
|
||||
return_len += ".length%d" % method.return_size_increment
|
||||
else:
|
||||
add_import(import_strings, class_dir_dict, my_dir_name, method.return_name)
|
||||
if runtime_error_on_serialize_dict[method.return_name.snake()]:
|
||||
template = template_method_retval_runtime_error_on_serialize
|
||||
else:
|
||||
template = template_method
|
||||
import_strings.append("import org.signal.zkgroup.ZkGroupError;")
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
append_jni_function_decl(jni_method_name, method.params, True, True)
|
||||
if method.return_name.snake() == "uuid":
|
||||
return_len = "UUIDUtil.UUID_LENGTH"
|
||||
elif return_len == None:
|
||||
return_len = method.return_name.camel() + ".SIZE"
|
||||
|
||||
|
||||
methods_string += template % {
|
||||
"contents": contents,
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"return_len": return_len,
|
||||
"param_decls": get_decls(method.params, import_strings, class_dir_dict, my_dir_name),
|
||||
"param_args": param_args,
|
||||
"jni_method_name": jni_method_name,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
"get_rand": get_rand,
|
||||
}
|
||||
|
||||
if c.dir_name.snake() != "":
|
||||
dir_section = "." + c.dir_name.snake()
|
||||
else:
|
||||
dir_section = ""
|
||||
|
||||
constructor_exception_decl = "throws InvalidInputException" # overwritten in needed
|
||||
runtime_error_bool = ""
|
||||
if c.check_valid_contents:
|
||||
if c.runtime_error_on_serialize:
|
||||
constructor_exception_decl = "" # overwritten in needed
|
||||
runtime_error_bool = ", true"
|
||||
check_valid_contents = template_check_valid_contents_constructor_runtime_error % {
|
||||
"class_name_lower_camel": c.class_name.lower_camel(),
|
||||
}
|
||||
jni_method_name = c.class_name.lower_camel() + "CheckValidContentsJNI"
|
||||
append_jni_check_valid_contents(jni_method_name)
|
||||
if my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.ZkGroupError;")
|
||||
import_strings.append("import org.signal.zkgroup.InvalidInputException;")
|
||||
else:
|
||||
constructor_exception_decl = "throws InvalidInputException" # overwritten in needed
|
||||
check_valid_contents = template_check_valid_contents_constructor % {
|
||||
"class_name_lower_camel": c.class_name.lower_camel(),
|
||||
}
|
||||
jni_method_name = c.class_name.lower_camel() + "CheckValidContentsJNI"
|
||||
append_jni_check_valid_contents(jni_method_name)
|
||||
if my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.InvalidInputException;")
|
||||
import_strings.append("import org.signal.zkgroup.ZkGroupError;")
|
||||
else:
|
||||
check_valid_contents = ""
|
||||
|
||||
if constructor_exception_decl.endswith("InvalidInputException") and my_dir_name.snake() != "":
|
||||
import_strings.append("import org.signal.zkgroup.InvalidInputException;")
|
||||
|
||||
if c.no_serialize:
|
||||
constructor_access = "private"
|
||||
else:
|
||||
constructor_access = "public"
|
||||
|
||||
if c.wrap_class == None:
|
||||
import_strings.append("import org.signal.zkgroup.internal.ByteArray;")
|
||||
import_strings = list(set(import_strings))
|
||||
import_strings.sort()
|
||||
|
||||
# constructors
|
||||
constructors_string = ""
|
||||
constructor_contents = "contents"
|
||||
constructor_contents_type = "byte[]"
|
||||
constructors_string += template_constructor % {
|
||||
"class_name": c.class_name.camel(),
|
||||
"constructor_contents": constructor_contents,
|
||||
"constructor_contents_type": constructor_contents_type,
|
||||
"constructor_access": constructor_access,
|
||||
"constructor_exception_decl": constructor_exception_decl,
|
||||
"runtime_error_bool": runtime_error_bool,
|
||||
"check_valid_contents": check_valid_contents,
|
||||
}
|
||||
|
||||
if c.string_contents == False:
|
||||
serialize_method = serialize_method_binary
|
||||
else:
|
||||
constructor_contents = 'contents.getBytes("UTF-8")'
|
||||
constructor_contents_type = "String"
|
||||
import_strings.append("import java.io.UnsupportedEncodingException;")
|
||||
serialize_method = serialize_method_string
|
||||
constructors_string += template_constructor_for_string_contents % {
|
||||
"class_name": c.class_name.camel(),
|
||||
"constructor_contents": constructor_contents,
|
||||
"constructor_contents_type": constructor_contents_type,
|
||||
"constructor_access": constructor_access,
|
||||
"constructor_exception_decl": constructor_exception_decl + ", UnsupportedEncodingException",
|
||||
"runtime_error_bool": runtime_error_bool,
|
||||
"check_valid_contents": check_valid_contents,
|
||||
}
|
||||
constructors_string = constructors_string[:-1]
|
||||
|
||||
if c.wrap_class != None:
|
||||
class_string = template_wrapping_class % {
|
||||
"imports": "\n".join(import_strings),
|
||||
"wrapped_class_type": c.wrap_class.camel(),
|
||||
"wrapped_class_var": c.wrap_class.lower_camel(),
|
||||
"dir_section": dir_section,
|
||||
"class_name": c.class_name.camel(),
|
||||
"size": c.class_len_int,
|
||||
"constructors": constructors_string,
|
||||
"static_methods": static_methods_string,
|
||||
"methods": methods_string,
|
||||
"serialize_method": serialize_method
|
||||
}
|
||||
else:
|
||||
class_string = template_class % {
|
||||
"imports": "\n".join(import_strings),
|
||||
"dir_section": dir_section,
|
||||
"class_name": c.class_name.camel(),
|
||||
"size": c.class_len_int,
|
||||
"constructors": constructors_string,
|
||||
"static_methods": static_methods_string,
|
||||
"methods": methods_string,
|
||||
"serialize_method": serialize_method
|
||||
}
|
||||
return class_string
|
||||
|
||||
|
||||
def produce_output(classes):
|
||||
|
||||
runtime_error_on_serialize_dict = {}
|
||||
class_dir_dict = {}
|
||||
for c in classes:
|
||||
runtime_error_on_serialize_dict[c.class_name.snake()] = c.runtime_error_on_serialize
|
||||
class_dir_dict[c.class_name.snake()] = c.dir_name
|
||||
|
||||
for c in classes:
|
||||
if c.no_class:
|
||||
continue
|
||||
if c.dir_name.snake() != "":
|
||||
f = open("java/%s/%s.java" % (c.dir_name.snake(), c.class_name.camel()), "w")
|
||||
else:
|
||||
f = open("java/%s.java" % c.class_name.camel(), "w")
|
||||
f.write(print_class(c, runtime_error_on_serialize_dict, class_dir_dict))
|
||||
f.close()
|
||||
f = open("java/internal/Native.java", "w")
|
||||
global native_string
|
||||
native_string += template_native_end
|
||||
f.write(native_string)
|
||||
f.close()
|
||||
@ -1,146 +0,0 @@
|
||||
|
||||
file_header = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::api;
|
||||
use crate::common::constants::*;
|
||||
use crate::common::simple_types;
|
||||
use crate::ffi::constants::*;
|
||||
"""
|
||||
|
||||
template_method_start = \
|
||||
"""
|
||||
pub fn %s_%s(%s) -> i32 {"""
|
||||
|
||||
template_load = \
|
||||
"""
|
||||
let %s: %s = match bincode::deserialize(%sIn) {
|
||||
Ok(result) => result,
|
||||
Err(_) => return %s,
|
||||
};
|
||||
"""
|
||||
|
||||
template_ret = \
|
||||
"""
|
||||
%sOut.copy_from_slice(&bincode::serialize(&%s).unwrap());"""
|
||||
|
||||
template_ret_simple = \
|
||||
"""
|
||||
%sOut.copy_from_slice(&%s);"""
|
||||
|
||||
template_ret_int = \
|
||||
"""
|
||||
%sOut.copy_from_slice(&%s.to_be_bytes());"""
|
||||
|
||||
|
||||
template_method_decl_end = \
|
||||
"""
|
||||
FFI_RETURN_OK
|
||||
}
|
||||
"""
|
||||
|
||||
def get_args(c, m, class_name, static=True):
|
||||
s = ""
|
||||
if not static:
|
||||
s += class_name.lower_camel() + "In: &[u8], "
|
||||
|
||||
for param in m.params:
|
||||
if param[0] == "int":
|
||||
s += param[1].lower_camel() + "In: u32, "
|
||||
elif param[0] == "long":
|
||||
s += param[1].lower_camel() + "In: u64, "
|
||||
else:
|
||||
s += param[1].lower_camel() + "In: &[u8], "
|
||||
|
||||
if m.return_type != "boolean":
|
||||
s += m.return_name.lower_camel() + "Out: &mut [u8], "
|
||||
|
||||
if len(s) != 0:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
|
||||
def print_method(c, m, rustClasses, static):
|
||||
s = ""
|
||||
|
||||
if c.wrap_class == None:
|
||||
class_name = c.class_name
|
||||
else:
|
||||
class_name = c.wrap_class
|
||||
# class_name = c.class_name
|
||||
|
||||
s += template_method_start % (class_name.camel(), m.method_name.lower_camel(), get_args(c, m, class_name, static))
|
||||
|
||||
if not static:
|
||||
if m.method_name.snake() != "check_valid_contents":
|
||||
error_name = "FFI_RETURN_INTERNAL_ERROR"
|
||||
elif m.verification:
|
||||
error_name = "FFI_RETURN_VERIFICATION_FAILED"
|
||||
else:
|
||||
error_name = "FFI_RETURN_INPUT_ERROR"
|
||||
if m.unused_self == True:
|
||||
s += template_load % ("_", rustClasses[class_name.snake()], class_name.lower_camel(), error_name)
|
||||
else:
|
||||
s += template_load % (class_name.snake(), rustClasses[class_name.snake()], class_name.lower_camel(), error_name)
|
||||
|
||||
if m.verification:
|
||||
error_name = "FFI_RETURN_VERIFICATION_FAILED"
|
||||
else:
|
||||
error_name = "FFI_RETURN_INPUT_ERROR"
|
||||
|
||||
for param in m.params:
|
||||
if param[0] == "int" or param[0] == "long" or param[0] == "byte[]":
|
||||
s += " let %s = %sIn;\n" % (param[1].snake(), param[1].lower_camel())
|
||||
elif param[1].snake() == "notary_signature":
|
||||
s += """ let mut notary_signature: simple_types::NotarySignatureBytes = [0u8; SIGNATURE_LEN];
|
||||
notary_signature.copy_from_slice(notarySignatureIn);\n""";
|
||||
else:
|
||||
s += template_load % (param[1].snake(), rustClasses[param[1].snake()], param[1].lower_camel(), error_name)
|
||||
|
||||
s += m.rustCode
|
||||
|
||||
if m.return_name.snake() == "change_signature" or m.return_name.snake() == "notary_signature" or \
|
||||
m.return_type == "byte[]":
|
||||
s += template_ret_simple % (m.return_name.lower_camel(), m.return_name.snake())
|
||||
elif m.return_type == "int" or m.return_type == "long":
|
||||
s += template_ret_int % (m.return_name.lower_camel(), m.return_name.snake())
|
||||
elif m.return_type != "boolean":
|
||||
s += template_ret % (m.return_name.lower_camel(), m.return_name.snake())
|
||||
|
||||
s += template_method_decl_end
|
||||
return s
|
||||
|
||||
def print_class(c, rustClasses):
|
||||
s = ""
|
||||
for method in c.static_methods:
|
||||
s += print_method(c, method, rustClasses, True)
|
||||
for method in c.methods:
|
||||
s += print_method(c, method, rustClasses, False)
|
||||
return s
|
||||
|
||||
|
||||
def produce_output(classes):
|
||||
|
||||
rustClasses = {}
|
||||
for c in classes:
|
||||
if c.wrap_class == None:
|
||||
class_name = c.class_name
|
||||
else:
|
||||
class_name = c.wrap_class
|
||||
rustClasses[c.class_name.snake()] = c.rust_class_name
|
||||
|
||||
s = file_header
|
||||
for c in classes:
|
||||
s += print_class(c, rustClasses)
|
||||
f = open("simpleapi/simpleapi.rs", "w")
|
||||
f.write(s)
|
||||
f.close()
|
||||
@ -1,679 +0,0 @@
|
||||
|
||||
template_class = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
%(imports)s
|
||||
|
||||
public class %(class_name)s : ByteArray {
|
||||
|
||||
public static let SIZE: Int = %(size)s
|
||||
%(static_methods)s%(constructors)s
|
||||
%(methods)s%(serialize_method)s}
|
||||
"""
|
||||
|
||||
template_constructor = \
|
||||
"""
|
||||
public init(contents: %(constructor_contents_type)s) %(constructor_exception_decl)s {
|
||||
try super.init(newContents: %(constructor_contents)s, expectedLength: %(class_name)s.SIZE%(runtime_error_bool)s)
|
||||
%(check_valid_contents)s
|
||||
}
|
||||
"""
|
||||
|
||||
template_constructor_for_string_contents = \
|
||||
"""
|
||||
public init(%(constructor_contents_type)s contents) %(constructor_exception_decl)s {
|
||||
try super.init(newContents: %(constructor_contents)s, expectedLength: %(class_name)s.SIZE%(runtime_error_bool)s)
|
||||
%(check_valid_contents)s
|
||||
}
|
||||
"""
|
||||
|
||||
serialize_method_string = \
|
||||
"""
|
||||
public func serialize() throws -> String {
|
||||
do {
|
||||
return new String(contents.clone(), "UTF-8")
|
||||
} catch UnsupportedEncodingException e) {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
serialize_method_binary = \
|
||||
"""
|
||||
public func serialize() -> [UInt8] {
|
||||
return contents
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
template_wrapping_class = \
|
||||
"""//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
%(imports)s
|
||||
|
||||
public class %(class_name)s {
|
||||
|
||||
let %(wrapped_class_var)s: %(wrapped_class_type)s
|
||||
%(static_methods)s
|
||||
public init(%(wrapped_class_var)s: %(wrapped_class_type)s) {
|
||||
self.%(wrapped_class_var)s = %(wrapped_class_var)s
|
||||
}
|
||||
%(methods)s
|
||||
}
|
||||
"""
|
||||
|
||||
template_check_valid_contents_constructor = \
|
||||
"""
|
||||
|
||||
let ffi_return = FFI_%(class_name_camel)s_checkValidContents(self.contents, UInt32(self.contents.count))
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.InvalidInput
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}"""
|
||||
|
||||
template_check_valid_contents_constructor_runtime_error = \
|
||||
"""
|
||||
|
||||
let ffi_return = FFI_%(class_name_camel)s_checkValidContents(self.contents, UInt32(self.contents.count))
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.IllegalArgument
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}"""
|
||||
|
||||
template_static_method = \
|
||||
"""
|
||||
%(access)s static func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: %(return_name)s.SIZE)%(get_rand)s
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
do {
|
||||
return try %(return_name)s(contents: newContents)
|
||||
} catch ZkGroupException.Invalid {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_static_method_retval_runtime_error_on_serialize = \
|
||||
"""
|
||||
public static func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: %(return_name)s.SIZE)%(get_rand)s
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
do {
|
||||
return try %(return_name)s(contents: newContents)
|
||||
} catch ZkGroupException.IllegalArgument {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_static_method_rand_wrapper = \
|
||||
"""
|
||||
public static func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var randomness: [UInt8] = Array(repeating: 0, count: Int(32))
|
||||
let result = SecRandomCopyBytes(kSecRandomDefault, randomness.count, &randomness)
|
||||
guard result == errSecSuccess else {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
|
||||
return try %(full_method_name)s(%(param_args)s)
|
||||
}
|
||||
"""
|
||||
|
||||
template_method = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: %(return_len)s)
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
do {
|
||||
return try %(return_name)s(contents: newContents)
|
||||
} catch ZkGroupException.InvalidInput {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_retval_runtime_error_on_serialize = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: Int(%(return_len)s))%(get_rand)s
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
return try %(return_name)s(contents: newContents)
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_bool = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s{
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s)%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_uuid = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: Int(%(return_len)s))
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
return UUIDUtil.deserialize(newContents)
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_bytearray = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> [UInt8] {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: Int(%(return_len)s))
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
return newContents
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_int = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> UInt32 {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: Int(4))
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
let data = Data(bytes: newContents)
|
||||
let value = UInt32(bigEndian: data.withUnsafeBytes { $0.pointee })
|
||||
return value
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_long = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> UInt64 {
|
||||
var newContents: [UInt8] = Array(repeating: 0, count: Int(8))
|
||||
|
||||
let ffi_return = FFI_%(jni_method_name)s(%(contents)s, %(param_args)s&newContents, UInt32(newContents.count))%(exception_check)s
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw ZkGroupException.ZkGroupError
|
||||
}
|
||||
|
||||
let data = Data(bytes: newContents)
|
||||
let value = UInt64(bigEndian: data.withUnsafeBytes { $0.pointee })
|
||||
return value
|
||||
}
|
||||
"""
|
||||
|
||||
template_method_rand_wrapper = \
|
||||
"""
|
||||
public func %(method_name)s(%(param_decls)s) %(exception_decl)s -> %(return_name)s {
|
||||
var randomness: [UInt8] = Array(repeating: 0, count: Int(32))
|
||||
let result = SecRandomCopyBytes(kSecRandomDefault, randomness.count, &randomness)
|
||||
guard result == errSecSuccess else {
|
||||
throw ZkGroupException.AssertionError
|
||||
}
|
||||
|
||||
return try %(full_method_name)s(%(param_args)s)
|
||||
}
|
||||
"""
|
||||
|
||||
def add_import(import_strings, class_dir_dict, my_dir_name, class_name):
|
||||
dir_name = class_dir_dict[class_name.snake()].snake()
|
||||
if len(dir_name)==0 and len(my_dir_name.snake()) == 0:
|
||||
return
|
||||
elif dir_name == my_dir_name.snake():
|
||||
return
|
||||
"""
|
||||
if dir_name:
|
||||
import_strings.append("import org.signal.zkgroup.%s.%s;" % (dir_name, class_name.camel()))
|
||||
else:
|
||||
import_strings.append("import org.signal.zkgroup.%s;" % (class_name.camel()))
|
||||
"""
|
||||
|
||||
def get_decls(params, import_strings, class_dir_dict, my_dir_name):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[1].snake() == "randomness":
|
||||
s += "randomness: [UInt8], "
|
||||
#SWIFT import_strings.append("import java.security.SecureRandom;")
|
||||
elif param[0] == "class":
|
||||
s += param[1].lower_camel() + ": " + param[1].camel() + ", "
|
||||
#SWIFT add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
elif param[0] == "byte[]":
|
||||
s += param[1].lower_camel() + ": [UInt8], "
|
||||
#SWIFT add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
elif param[0] == "int":
|
||||
s += param[1].lower_camel() + ": UInt32, "
|
||||
#SWIFT add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
elif param[0] == "long":
|
||||
s += param[1].lower_camel() + ": UInt64, "
|
||||
#SWIFT add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
elif param[0] == "UUID":
|
||||
s += param[1].lower_camel() + ": ZKGUuid, "
|
||||
#SWIFT add_import(import_strings, class_dir_dict, my_dir_name, param[1])
|
||||
else:
|
||||
s += param[1].lower_camel() + ": " + param[0] + ", "
|
||||
if len(s) != 0:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def get_rand_wrapper_decls(params):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[1].snake() != "randomness":
|
||||
if param[0] == "class":
|
||||
s += param[1].lower_camel() + ": " + param[1].camel() + ", "
|
||||
elif param[0] == "byte[]":
|
||||
s += param[1].lower_camel() + ": [UInt8], "
|
||||
elif param[0] == "int":
|
||||
s += param[1].lower_camel() + ": UInt32, "
|
||||
elif param[0] == "long":
|
||||
s += param[1].lower_camel() + ": UInt64, "
|
||||
elif param[0] == "UUID":
|
||||
s += param[1].lower_camel() + ": ZKGUuid, "
|
||||
else:
|
||||
s += param[1].lower_camel() + ": " + param[0] + ", "
|
||||
if len(s) != 0:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
|
||||
def get_args(params, import_strings, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[0] == "byte[]" or param[0] == "int" or param[0] == "long":
|
||||
term = param[1].lower_camel()
|
||||
# SWIFT elif param[0] == "UUID":
|
||||
# SWIFT term = "UUIDUtil.serialize(" + param[1].lower_camel() + ")"
|
||||
elif param[1].snake() == "randomness":
|
||||
term = "randomness"
|
||||
else:
|
||||
term = param[1].lower_camel() + ".getInternalContentsForFFI()"
|
||||
|
||||
if param[0] == "int" or param[0] == "long":
|
||||
s += term + ", "
|
||||
else:
|
||||
s += term + ", UInt32(" + term + ".count), "
|
||||
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def get_jni_arg_decls(params, selfBool, commaAtEndBool):
|
||||
s = ""
|
||||
if selfBool:
|
||||
s += "byte[] self, "
|
||||
counter = 0
|
||||
for param in params:
|
||||
if param[0] == "byte[]":
|
||||
s += "byte[] %s, " % param[1].lower_camel()
|
||||
elif param[0] == "int":
|
||||
s += "int %s, " % param[1].lower_camel()
|
||||
elif param[0] == "long":
|
||||
s += "long %s, " % param[1].lower_camel()
|
||||
# elif param[0] == "UUID":
|
||||
# s += "byte[] %s, " % param[1].lower_camel()
|
||||
elif param[1].snake() == "randomness":
|
||||
s += "byte[] %s, " % param[1].lower_camel()
|
||||
else:
|
||||
s += "byte[] %s, " % param[1].lower_camel()
|
||||
counter += 1
|
||||
|
||||
if len(s) != 0 and not commaAtEndBool:
|
||||
s = s[:-2]
|
||||
|
||||
if commaAtEndBool:
|
||||
s += "byte[] output"
|
||||
|
||||
return s
|
||||
|
||||
def get_rand_wrapper_args(params, commaAtEnd):
|
||||
s = ""
|
||||
for param in params:
|
||||
if param[0] == "byte[]":
|
||||
s += param[1].lower_camel() + ": " + param[1].lower_camel() + ", "
|
||||
else:
|
||||
s += param[1].lower_camel() + ": " + param[1].lower_camel() + ", "
|
||||
if len(s) != 0 and not commaAtEnd:
|
||||
s = s[:-2]
|
||||
return s
|
||||
|
||||
def print_class(c, runtime_error_on_serialize_dict, class_dir_dict):
|
||||
static_methods_string = ""
|
||||
if len(c.methods) == 0 and len(c.static_methods) == 0:
|
||||
import_strings = []
|
||||
else:
|
||||
import_strings = [\
|
||||
"import libzkgroup",
|
||||
"import Foundation"
|
||||
]
|
||||
|
||||
my_dir_name = c.dir_name
|
||||
|
||||
if c.wrap_class == None:
|
||||
contents = "self.contents"
|
||||
else:
|
||||
contents = c.wrap_class.lower_camel() + ".getInternalContentsForFFI()"
|
||||
add_import(import_strings, class_dir_dict, my_dir_name, c.wrap_class)
|
||||
contents += ", UInt32(%s.count)" % contents
|
||||
|
||||
for method in c.static_methods:
|
||||
|
||||
exception_decl = "throws "
|
||||
exception_check =""
|
||||
if len(method.params) > 1 or (len(method.params) == 1 and not method.method_name.snake().endswith("_deterministic")):
|
||||
if method.runtime_error == False:
|
||||
if method.verification == False:
|
||||
#if my_dir_name.snake() != "":
|
||||
# import_strings.append("import org.signal.zkgroup.VerificationFailedException;")
|
||||
exception_decl = "throws "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}"""
|
||||
else:
|
||||
exception_decl = "throws VerificationFailed "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_VERIFICATION_FAILED) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}"""
|
||||
|
||||
access = "public"
|
||||
method_name = method.method_name.lower_camel()
|
||||
get_rand = ""
|
||||
if method.method_name.snake().endswith("_deterministic"):
|
||||
method_name = method.method_name.lower_camel()[:-len("Deterministic")]
|
||||
param_args = get_rand_wrapper_args(method.params, False)
|
||||
get_rand = ""
|
||||
static_methods_string += template_static_method_rand_wrapper % {
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"full_method_name": method_name,
|
||||
"param_decls": get_rand_wrapper_decls(method.params),
|
||||
"param_args": param_args,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
}
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
if c.wrap_class == None:
|
||||
jni_method_name = c.class_name.camel() + "_" + method.method_name.lower_camel()
|
||||
else:
|
||||
jni_method_name = c.wrap_class.camel() + "_" + method.method_name.lower_camel()
|
||||
if runtime_error_on_serialize_dict[method.return_name.snake()]:
|
||||
template = template_static_method_retval_runtime_error_on_serialize
|
||||
else:
|
||||
template = template_static_method
|
||||
static_methods_string += template % {
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"return_len": c.class_len,
|
||||
"param_decls": get_decls(method.params, import_strings, class_dir_dict, my_dir_name),
|
||||
"param_args": param_args,
|
||||
"jni_method_name": jni_method_name,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
"get_rand": get_rand,
|
||||
}
|
||||
|
||||
methods_string = ""
|
||||
for method in c.methods:
|
||||
|
||||
if method.method_name.snake() == "check_valid_contents":
|
||||
continue
|
||||
|
||||
exception_decl = "throws "
|
||||
exception_check =""
|
||||
if len(method.params) != 0:
|
||||
if method.runtime_error == False:
|
||||
if method.verification == False:
|
||||
#if my_dir_name.snake() != "":
|
||||
# import_strings.append("import org.signal.zkgroup.VerificationFailedException;")
|
||||
exception_decl = "throws "
|
||||
exception_check ="""\n if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}"""
|
||||
else:
|
||||
exception_decl = "throws "
|
||||
exception_check ="""\n if (ffi_return == Native.FtFI_RETURN_VERIFICATION_FAILED) {
|
||||
throw ZkGroupException.VerificationFailed
|
||||
}"""
|
||||
|
||||
access = "public"
|
||||
method_name = method.method_name.lower_camel()
|
||||
get_rand = ""
|
||||
if method.method_name.snake().endswith("_deterministic"):
|
||||
method_name = method.method_name.lower_camel()[:-len("Deterministic")]
|
||||
param_args = get_rand_wrapper_args(method.params, False)
|
||||
get_rand = """\n byte[] random = byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);"""
|
||||
methods_string += template_method_rand_wrapper % {
|
||||
"contents": contents,
|
||||
"method_name": method_name,
|
||||
"return_name": method.return_name.camel(),
|
||||
"full_method_name": method_name,
|
||||
"param_decls": get_rand_wrapper_decls(method.params),
|
||||
"param_args": param_args,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
}
|
||||
|
||||
if c.wrap_class == None:
|
||||
jni_method_name = c.class_name.camel() + "_" + method.method_name.lower_camel()
|
||||
else:
|
||||
jni_method_name = c.wrap_class.camel() + "_" + method.method_name.lower_camel()
|
||||
|
||||
return_name = None
|
||||
return_len = None
|
||||
|
||||
if method.return_type == "UUID":
|
||||
return_name = "ZKGUuid"
|
||||
return_len = "ZKGUuid.SIZE"
|
||||
|
||||
if method.return_type == "boolean":
|
||||
template = template_method_bool
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
elif method.return_type == "int":
|
||||
template = template_method_int
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
elif method.return_type == "long":
|
||||
template = template_method_long
|
||||
param_args = get_args(method.params, import_strings, False)
|
||||
elif method.return_type == "byte[]": # copied from UUID?
|
||||
template = template_method_bytearray
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
return_len = method.params[0][1].lower_camel() # hardcode to first arg
|
||||
if method.return_size_increment >= 0:
|
||||
return_len += ".count+%d" % method.return_size_increment
|
||||
if method.return_size_increment < 0:
|
||||
return_len += ".count+%d" % method.return_size_increment
|
||||
else:
|
||||
add_import(import_strings, class_dir_dict, my_dir_name, method.return_name)
|
||||
if runtime_error_on_serialize_dict[method.return_name.snake()]:
|
||||
template = template_method_retval_runtime_error_on_serialize
|
||||
else:
|
||||
template = template_method
|
||||
param_args = get_args(method.params, import_strings, True)
|
||||
if return_name == None:
|
||||
return_name = method.return_name.camel()
|
||||
if return_len == None:
|
||||
return_len = method.return_name.camel() + ".SIZE"
|
||||
|
||||
|
||||
methods_string += template % {
|
||||
"contents": contents,
|
||||
"method_name": method_name,
|
||||
"return_name": return_name,
|
||||
"return_len": return_len,
|
||||
"param_decls": get_decls(method.params, import_strings, class_dir_dict, my_dir_name),
|
||||
"param_args": param_args,
|
||||
"jni_method_name": jni_method_name,
|
||||
"access": access,
|
||||
"exception_decl": exception_decl,
|
||||
"exception_check": exception_check,
|
||||
"get_rand": get_rand,
|
||||
}
|
||||
|
||||
if c.dir_name.snake() != "":
|
||||
dir_section = "." + c.dir_name.snake()
|
||||
else:
|
||||
dir_section = ""
|
||||
|
||||
constructor_exception_decl = "throws " # overwritten in needed
|
||||
runtime_error_bool = ""
|
||||
if c.check_valid_contents:
|
||||
if c.runtime_error_on_serialize:
|
||||
constructor_exception_decl = "throws " # overwritten in needed
|
||||
runtime_error_bool = ", unrecoverable: true"
|
||||
check_valid_contents = template_check_valid_contents_constructor_runtime_error % {
|
||||
"class_name_camel": c.class_name.camel(),
|
||||
}
|
||||
jni_method_name = c.class_name.lower_camel() + "CheckValidContentsFFI"
|
||||
else:
|
||||
constructor_exception_decl = "throws " # overwritten in needed
|
||||
check_valid_contents = template_check_valid_contents_constructor % {
|
||||
"class_name_camel": c.class_name.camel(),
|
||||
}
|
||||
jni_method_name = c.class_name.lower_camel() + "CheckValidContentsFFI"
|
||||
else:
|
||||
check_valid_contents = ""
|
||||
|
||||
if c.no_serialize:
|
||||
constructor_access = "private"
|
||||
else:
|
||||
constructor_access = "public"
|
||||
|
||||
import_strings = list(set(import_strings))
|
||||
import_strings.sort()
|
||||
|
||||
# constructors
|
||||
constructors_string = ""
|
||||
constructor_contents = "contents"
|
||||
constructor_contents_type = "[UInt8]"
|
||||
constructors_string += template_constructor % {
|
||||
"class_name": c.class_name.camel(),
|
||||
"constructor_contents": constructor_contents,
|
||||
"constructor_contents_type": constructor_contents_type,
|
||||
"constructor_access": constructor_access,
|
||||
"constructor_exception_decl": constructor_exception_decl,
|
||||
"runtime_error_bool": runtime_error_bool,
|
||||
"check_valid_contents": check_valid_contents,
|
||||
}
|
||||
|
||||
# if c.string_contents == False:
|
||||
if True:
|
||||
serialize_method = serialize_method_binary
|
||||
else:
|
||||
constructor_contents = 'contents.getBytes("UTF-8")'
|
||||
constructor_contents_type = "String"
|
||||
serialize_method = serialize_method_string
|
||||
constructors_string += template_constructor_for_string_contents % {
|
||||
"class_name": c.class_name.camel(),
|
||||
"constructor_contents": constructor_contents,
|
||||
"constructor_contents_type": constructor_contents_type,
|
||||
"constructor_access": constructor_access,
|
||||
"constructor_exception_decl": constructor_exception_decl + ", UnsupportedEncodingException",
|
||||
"runtime_error_bool": runtime_error_bool,
|
||||
"check_valid_contents": check_valid_contents,
|
||||
}
|
||||
constructors_string = constructors_string[:-1]
|
||||
|
||||
if c.wrap_class != None:
|
||||
class_string = template_wrapping_class % {
|
||||
"imports": "\n".join(import_strings),
|
||||
"wrapped_class_type": c.wrap_class.camel(),
|
||||
"wrapped_class_var": c.wrap_class.lower_camel(),
|
||||
"dir_section": dir_section,
|
||||
"class_name": c.class_name.camel(),
|
||||
"size": c.class_len_int,
|
||||
"constructors": constructors_string,
|
||||
"static_methods": static_methods_string,
|
||||
"methods": methods_string,
|
||||
"serialize_method": serialize_method
|
||||
}
|
||||
else:
|
||||
class_string = template_class % {
|
||||
"imports": "\n".join(import_strings),
|
||||
"dir_section": dir_section,
|
||||
"class_name": c.class_name.camel(),
|
||||
"size": c.class_len_int,
|
||||
"constructors": constructors_string,
|
||||
"static_methods": static_methods_string,
|
||||
"methods": methods_string,
|
||||
"serialize_method": serialize_method
|
||||
}
|
||||
return class_string
|
||||
|
||||
def produce_output(classes):
|
||||
|
||||
runtime_error_on_serialize_dict = {}
|
||||
class_dir_dict = {}
|
||||
for c in classes:
|
||||
runtime_error_on_serialize_dict[c.class_name.snake()] = c.runtime_error_on_serialize
|
||||
class_dir_dict[c.class_name.snake()] = c.dir_name
|
||||
|
||||
for c in classes:
|
||||
if c.no_class:
|
||||
continue
|
||||
f = open("swift/%s.swift" % c.class_name.camel(), "w")
|
||||
f.write(print_class(c, runtime_error_on_serialize_dict, class_dir_dict))
|
||||
f.close()
|
||||
@ -1,75 +0,0 @@
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
|
||||
version = '0.8.1'
|
||||
group = 'org.signal'
|
||||
|
||||
def isReleaseBuild() {
|
||||
return version.contains("SNAPSHOT") == false
|
||||
}
|
||||
|
||||
def getReleaseRepositoryUrl() {
|
||||
return hasProperty('sonatypeRepo') ? sonatypeRepo
|
||||
: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
|
||||
}
|
||||
|
||||
def getRepositoryUsername() {
|
||||
return hasProperty('whisperSonatypeUsername') ? whisperSonatypeUsername : ""
|
||||
}
|
||||
|
||||
def getRepositoryPassword() {
|
||||
return hasProperty('whisperSonatypePassword') ? whisperSonatypePassword : ""
|
||||
}
|
||||
|
||||
signing {
|
||||
required { isReleaseBuild() && gradle.taskGraph.hasTask('uploadArchives') }
|
||||
sign configurations.archives
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
configuration = configurations.archives
|
||||
repositories.mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
repository(url: getReleaseRepositoryUrl()) {
|
||||
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
|
||||
}
|
||||
|
||||
pom.project {
|
||||
name archivesBaseName
|
||||
description 'Zero Knowledge Groups library'
|
||||
url 'https://github.com/signalapp/zkgroup'
|
||||
|
||||
scm {
|
||||
url 'scm:git@github.com:signalapp/zkgroup.git'
|
||||
connection 'scm:git@github.com:signalapp/zkgroup.git'
|
||||
developerConnection 'scm:git@github.com:signalapp/zkgroup.git'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'GPLv3'
|
||||
url 'https://www.gnu.org/licenses/gpl-3.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
name 'Trevor Perrin'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task installArchives(type: Upload) {
|
||||
group 'Deploy'
|
||||
description 'Installs the artifacts to the local Maven repository.'
|
||||
configuration = configurations['archives']
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
repository url: "file://${System.properties['user.home']}/.m2/repository"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
Acquire::Check-Valid-Until "false";
|
||||
Acquire::Languages "none";
|
||||
Binary::apt-get::Acquire::AllowInsecureRepositories "false";
|
||||
|
||||
APT::Install-Recommends "false";
|
||||
APT::Immediate-Configure "false";
|
||||
@ -1 +0,0 @@
|
||||
openjdk-8-jdk=8u252-b09-1
|
||||
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
while read dep; do
|
||||
dep_name=$(echo $dep | cut -f1 -d '=')
|
||||
version=$(dpkg -s $dep_name | grep 'Version: ' | cut -f2 -d ' ')
|
||||
echo "$dep_name=$version"
|
||||
done < $1
|
||||
@ -1,2 +0,0 @@
|
||||
deb http://snapshot.debian.org/archive/debian-security/20200731T201723Z stretch/updates main
|
||||
deb http://snapshot.debian.org/archive/debian/20200731T211026Z/ unstable main
|
||||
13
ffi/android/.gitignore
vendored
@ -1,13 +0,0 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
@ -1,61 +0,0 @@
|
||||
# Building zkgroup for Android
|
||||
This document describes how to build and package zkgroup for Android. We assume the repository is already available (i.e. cloned with git).
|
||||
|
||||
## tl;dr
|
||||
```
|
||||
$ ./gradlew build
|
||||
```
|
||||
|
||||
## From Zero
|
||||
|
||||
### Linux (Ubuntu 18.04)
|
||||
Install dependencies (if not already done) and Rust.
|
||||
|
||||
Example:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install build-essential wget curl git vim
|
||||
sudo apt install python2.7 python-pip
|
||||
sudo apt install openjdk-8-jdk
|
||||
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
`rustup show` should indicate that the `x86_64-unknown-linux-gnu` is the host and stable, active toolchain.
|
||||
|
||||
#### Install Other Dependencies
|
||||
|
||||
##### Android Studio
|
||||
This is recommended. Add the NDK, LLDB, Android SDK Tools, and any updates as needed. You may also need:
|
||||
```
|
||||
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386
|
||||
```
|
||||
|
||||
##### Android SDK & NDK
|
||||
Set SDK and NDK locations (at the end of ~/.bashrc). For example:
|
||||
```
|
||||
export ANDROID_HOME=/home/signal/Android/Sdk
|
||||
export NDK_HOME=/home/signal/Android/Sdk/ndk/21.0.6113669
|
||||
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
|
||||
```
|
||||
|
||||
##### Android Rust Targets
|
||||
```
|
||||
rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android
|
||||
```
|
||||
|
||||
##### Install Cargo NDK
|
||||
```
|
||||
cargo install cargo-ndk
|
||||
```
|
||||
|
||||
## Building
|
||||
From the project root directory, using gradle:
|
||||
```
|
||||
./gradlew build
|
||||
```
|
||||
|
||||
This will build all Rust and Java dependencies, and setup the AAR file(s) necessary for testing.
|
||||
|
||||
## Packaging
|
||||
TBD
|
||||
@ -1,21 +0,0 @@
|
||||
|
||||
.PHONY: so
|
||||
.PHONY: org_signal_zkgroup_ZKGroup.h
|
||||
|
||||
so:
|
||||
cargo build --target aarch64-linux-android --release
|
||||
cargo build --target armv7-linux-androideabi --release
|
||||
cargo build --target i686-linux-android --release
|
||||
cargo build --target x86_64-linux-android --release
|
||||
cp ../../target/armv7-linux-androideabi/release/libzkgroup.so \
|
||||
zkgroup/src/main/jniLibs/armeabi-v7a/
|
||||
cp ../../target/aarch64-linux-android/release/libzkgroup.so \
|
||||
zkgroup/src/main/jniLibs/arm64-v8a/
|
||||
cp ../../target/i686-linux-android/release/libzkgroup.so \
|
||||
zkgroup/src/main/jniLibs/x86/
|
||||
cp ../../target/x86_64-linux-android/release/libzkgroup.so \
|
||||
zkgroup/src/main/jniLibs/x86_64/
|
||||
|
||||
org_signal_zkgroup_ZKGroup.h:
|
||||
javac -h . zkgroup/src/main/java/org/signal/zkgroup/ZKGroup.java
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
1
ffi/android/exampleApp/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/build
|
||||
@ -1,19 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "org.signal.zkgroupdemo"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':ffi:android:lib')
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.signal.trevor">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -1,27 +0,0 @@
|
||||
package org.signal.trevor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import org.signal.zkgroup.ServerSecretParams;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class MainActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
}
|
||||
|
||||
public void test(View view) {
|
||||
ServerSecretParams serverSecretParams = ServerSecretParams.generate();
|
||||
|
||||
Log.d(TAG, String.format("Keypair contents: %s", Arrays.toString(serverSecretParams.serialize())));
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="test"
|
||||
android:text="Test"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
||||
@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name">TrevorsThing</string>
|
||||
</resources>
|
||||
@ -1,11 +0,0 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@ -1,15 +0,0 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
|
||||
2
ffi/android/lib/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
/build
|
||||
src/main/jniLibs
|
||||
@ -1,28 +0,0 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply from: '../../../deploy.gradle'
|
||||
|
||||
archivesBaseName = 'zkgroup-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn ':makeAndroid'
|
||||
}
|
||||
|
||||
tasks.withType(AbstractArchiveTask) {
|
||||
preserveFileTimestamps = false
|
||||
reproducibleFileOrder = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':ffi:java')
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
<manifest package="org.signal.zkgroup" />
|
||||
@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name">ZKGroup Lib</string>
|
||||
</resources>
|
||||
@ -1,3 +0,0 @@
|
||||
.PHONY: zkgroup.h
|
||||
zkgroup.h:
|
||||
cbindgen --lang c ../../rust -o zkgroup.h
|
||||
431
ffi/c/zkgroup.h
@ -1,431 +0,0 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NUM_AUTH_CRED_ATTRIBUTES 3
|
||||
|
||||
#define NUM_PROFILE_KEY_CRED_ATTRIBUTES 4
|
||||
|
||||
#define NUM_RECEIPT_CRED_ATTRIBUTES 2
|
||||
|
||||
#define AES_KEY_LEN 32
|
||||
|
||||
#define AESGCM_NONCE_LEN 12
|
||||
|
||||
#define AESGCM_TAG_LEN 16
|
||||
|
||||
#define GROUP_MASTER_KEY_LEN 32
|
||||
|
||||
#define GROUP_SECRET_PARAMS_LEN 289
|
||||
|
||||
#define GROUP_PUBLIC_PARAMS_LEN 97
|
||||
|
||||
#define GROUP_IDENTIFIER_LEN 32
|
||||
|
||||
#define AUTH_CREDENTIAL_LEN 181
|
||||
|
||||
#define AUTH_CREDENTIAL_PRESENTATION_LEN 493
|
||||
|
||||
#define AUTH_CREDENTIAL_RESPONSE_LEN 361
|
||||
|
||||
#define PROFILE_KEY_LEN 32
|
||||
|
||||
#define PROFILE_KEY_CIPHERTEXT_LEN 65
|
||||
|
||||
#define PROFILE_KEY_COMMITMENT_LEN 97
|
||||
|
||||
#define PROFILE_KEY_CREDENTIAL_LEN 145
|
||||
|
||||
#define PROFILE_KEY_CREDENTIAL_PRESENTATION_LEN 713
|
||||
|
||||
#define PROFILE_KEY_CREDENTIAL_REQUEST_LEN 329
|
||||
|
||||
#define PROFILE_KEY_CREDENTIAL_REQUEST_CONTEXT_LEN 473
|
||||
|
||||
#define PROFILE_KEY_CREDENTIAL_RESPONSE_LEN 457
|
||||
|
||||
#define PROFILE_KEY_VERSION_LEN 32
|
||||
|
||||
#define PROFILE_KEY_VERSION_ENCODED_LEN 64
|
||||
|
||||
#define RECEIPT_CREDENTIAL_LEN 129
|
||||
|
||||
#define RECEIPT_CREDENTIAL_PRESENTATION_LEN 329
|
||||
|
||||
#define RECEIPT_CREDENTIAL_REQUEST_LEN 97
|
||||
|
||||
#define RECEIPT_CREDENTIAL_REQUEST_CONTEXT_LEN 177
|
||||
|
||||
#define RECEIPT_CREDENTIAL_RESPONSE_LEN 409
|
||||
|
||||
#define RECEIPT_SERIAL_LEN 16
|
||||
|
||||
#define RESERVED_LEN 1
|
||||
|
||||
#define SERVER_SECRET_PARAMS_LEN 1121
|
||||
|
||||
#define SERVER_PUBLIC_PARAMS_LEN 225
|
||||
|
||||
#define UUID_CIPHERTEXT_LEN 65
|
||||
|
||||
#define RANDOMNESS_LEN 32
|
||||
|
||||
#define SIGNATURE_LEN 64
|
||||
|
||||
#define UUID_LEN 16
|
||||
|
||||
#define FFI_RETURN_OK 0
|
||||
|
||||
#define FFI_RETURN_INTERNAL_ERROR 1
|
||||
|
||||
#define FFI_RETURN_INPUT_ERROR 2
|
||||
|
||||
int32_t FFI_ProfileKey_getCommitment(const uint8_t *profileKey,
|
||||
uint32_t profileKeyLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint8_t *profileKeyCommitmentOut,
|
||||
uint32_t profileKeyCommitmentLen);
|
||||
|
||||
int32_t FFI_ProfileKey_getProfileKeyVersion(const uint8_t *profileKey,
|
||||
uint32_t profileKeyLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint8_t *profileKeyVersionOut,
|
||||
uint32_t profileKeyVersionLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCommitment_checkValidContents(const uint8_t *profileKeyCommitment,
|
||||
uint32_t profileKeyCommitmentLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_generateDeterministic(const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
uint8_t *groupSecretParamsOut,
|
||||
uint32_t groupSecretParamsLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_deriveFromMasterKey(const uint8_t *groupMasterKey,
|
||||
uint32_t groupMasterKeyLen,
|
||||
uint8_t *groupSecretParamsOut,
|
||||
uint32_t groupSecretParamsLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_checkValidContents(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_getMasterKey(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
uint8_t *groupMasterKeyOut,
|
||||
uint32_t groupMasterKeyLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_getPublicParams(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
uint8_t *groupPublicParamsOut,
|
||||
uint32_t groupPublicParamsLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_encryptUuid(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint8_t *uuidCiphertextOut,
|
||||
uint32_t uuidCiphertextLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_decryptUuid(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *uuidCiphertext,
|
||||
uint32_t uuidCiphertextLen,
|
||||
uint8_t *uuidOut,
|
||||
uint32_t uuidLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_encryptProfileKey(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *profileKey,
|
||||
uint32_t profileKeyLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint8_t *profileKeyCiphertextOut,
|
||||
uint32_t profileKeyCiphertextLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_decryptProfileKey(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *profileKeyCiphertext,
|
||||
uint32_t profileKeyCiphertextLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint8_t *profileKeyOut,
|
||||
uint32_t profileKeyLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_encryptBlobDeterministic(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *plaintext,
|
||||
uint32_t plaintextLen,
|
||||
uint8_t *blobCiphertextOut,
|
||||
uint32_t blobCiphertextLen);
|
||||
|
||||
int32_t FFI_GroupSecretParams_decryptBlob(const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *blobCiphertext,
|
||||
uint32_t blobCiphertextLen,
|
||||
uint8_t *plaintextOut,
|
||||
uint32_t plaintextLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_generateDeterministic(const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
uint8_t *serverSecretParamsOut,
|
||||
uint32_t serverSecretParamsLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_checkValidContents(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_getPublicParams(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
uint8_t *serverPublicParamsOut,
|
||||
uint32_t serverPublicParamsLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_signDeterministic(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *message,
|
||||
uint32_t messageLen,
|
||||
uint8_t *notarySignatureOut,
|
||||
uint32_t notarySignatureLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_receiveAuthCredential(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint32_t redemptionTime,
|
||||
const uint8_t *authCredentialResponse,
|
||||
uint32_t authCredentialResponseLen,
|
||||
uint8_t *authCredentialOut,
|
||||
uint32_t authCredentialLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_createAuthCredentialPresentationDeterministic(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *authCredential,
|
||||
uint32_t authCredentialLen,
|
||||
uint8_t *authCredentialPresentationOut,
|
||||
uint32_t authCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_createProfileKeyCredentialRequestContextDeterministic(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
const uint8_t *profileKey,
|
||||
uint32_t profileKeyLen,
|
||||
uint8_t *profileKeyCredentialRequestContextOut,
|
||||
uint32_t profileKeyCredentialRequestContextLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_receiveProfileKeyCredential(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *profileKeyCredentialRequestContext,
|
||||
uint32_t profileKeyCredentialRequestContextLen,
|
||||
const uint8_t *profileKeyCredentialResponse,
|
||||
uint32_t profileKeyCredentialResponseLen,
|
||||
uint8_t *profileKeyCredentialOut,
|
||||
uint32_t profileKeyCredentialLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_createProfileKeyCredentialPresentationDeterministic(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *groupSecretParams,
|
||||
uint32_t groupSecretParamsLen,
|
||||
const uint8_t *profileKeyCredential,
|
||||
uint32_t profileKeyCredentialLen,
|
||||
uint8_t *profileKeyCredentialPresentationOut,
|
||||
uint32_t profileKeyCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_createReceiptCredentialRequestContextDeterministic(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *receiptSerial,
|
||||
uint32_t receiptSerialLen,
|
||||
uint8_t *receiptCredentialRequestContextOut,
|
||||
uint32_t receiptCredentialRequestContextLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_receiveReceiptCredential(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *receiptCredentialRequestContext,
|
||||
uint32_t receiptCredentialRequestContextLen,
|
||||
const uint8_t *receiptCredentialResponse,
|
||||
uint32_t receiptCredentialResponseLen,
|
||||
uint8_t *receiptCredentialOut,
|
||||
uint32_t receiptCredentialLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_createReceiptCredentialPresentationDeterministic(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *receiptCredential,
|
||||
uint32_t receiptCredentialLen,
|
||||
uint8_t *receiptCredentialPresentationOut,
|
||||
uint32_t receiptCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_issueAuthCredentialDeterministic(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
uint32_t redemptionTime,
|
||||
uint8_t *authCredentialResponseOut,
|
||||
uint32_t authCredentialResponseLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_verifyAuthCredentialPresentation(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *groupPublicParams,
|
||||
uint32_t groupPublicParamsLen,
|
||||
const uint8_t *authCredentialPresentation,
|
||||
uint32_t authCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_issueProfileKeyCredentialDeterministic(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *profileKeyCredentialRequest,
|
||||
uint32_t profileKeyCredentialRequestLen,
|
||||
const uint8_t *uuid,
|
||||
uint32_t uuidLen,
|
||||
const uint8_t *profileKeyCommitment,
|
||||
uint32_t profileKeyCommitmentLen,
|
||||
uint8_t *profileKeyCredentialResponseOut,
|
||||
uint32_t profileKeyCredentialResponseLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_verifyProfileKeyCredentialPresentation(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *groupPublicParams,
|
||||
uint32_t groupPublicParamsLen,
|
||||
const uint8_t *profileKeyCredentialPresentation,
|
||||
uint32_t profileKeyCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_issueReceiptCredentialDeterministic(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *randomness,
|
||||
uint32_t randomnessLen,
|
||||
const uint8_t *receiptCredentialRequest,
|
||||
uint32_t receiptCredentialRequestLen,
|
||||
uint64_t receiptExpirationTime,
|
||||
uint64_t receiptLevel,
|
||||
uint8_t *receiptCredentialResponseOut,
|
||||
uint32_t receiptCredentialResponseLen);
|
||||
|
||||
int32_t FFI_ServerSecretParams_verifyReceiptCredentialPresentation(const uint8_t *serverSecretParams,
|
||||
uint32_t serverSecretParamsLen,
|
||||
const uint8_t *receiptCredentialPresentation,
|
||||
uint32_t receiptCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_GroupPublicParams_checkValidContents(const uint8_t *groupPublicParams,
|
||||
uint32_t groupPublicParamsLen);
|
||||
|
||||
int32_t FFI_GroupPublicParams_getGroupIdentifier(const uint8_t *groupPublicParams,
|
||||
uint32_t groupPublicParamsLen,
|
||||
uint8_t *groupIdentifierOut,
|
||||
uint32_t groupIdentifierLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_checkValidContents(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen);
|
||||
|
||||
int32_t FFI_ServerPublicParams_verifySignature(const uint8_t *serverPublicParams,
|
||||
uint32_t serverPublicParamsLen,
|
||||
const uint8_t *message,
|
||||
uint32_t messageLen,
|
||||
const uint8_t *notarySignature,
|
||||
uint32_t notarySignatureLen);
|
||||
|
||||
int32_t FFI_AuthCredentialResponse_checkValidContents(const uint8_t *authCredentialResponse,
|
||||
uint32_t authCredentialResponseLen);
|
||||
|
||||
int32_t FFI_AuthCredential_checkValidContents(const uint8_t *authCredential,
|
||||
uint32_t authCredentialLen);
|
||||
|
||||
int32_t FFI_AuthCredentialPresentation_checkValidContents(const uint8_t *authCredentialPresentation,
|
||||
uint32_t authCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_AuthCredentialPresentation_getUuidCiphertext(const uint8_t *authCredentialPresentation,
|
||||
uint32_t authCredentialPresentationLen,
|
||||
uint8_t *uuidCiphertextOut,
|
||||
uint32_t uuidCiphertextLen);
|
||||
|
||||
int32_t FFI_AuthCredentialPresentation_getRedemptionTime(const uint8_t *authCredentialPresentation,
|
||||
uint32_t authCredentialPresentationLen,
|
||||
uint8_t *redemptionTimeOut,
|
||||
uint32_t redemptionTimeLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialRequestContext_checkValidContents(const uint8_t *profileKeyCredentialRequestContext,
|
||||
uint32_t profileKeyCredentialRequestContextLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialRequestContext_getRequest(const uint8_t *profileKeyCredentialRequestContext,
|
||||
uint32_t profileKeyCredentialRequestContextLen,
|
||||
uint8_t *profileKeyCredentialRequestOut,
|
||||
uint32_t profileKeyCredentialRequestLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialRequest_checkValidContents(const uint8_t *profileKeyCredentialRequest,
|
||||
uint32_t profileKeyCredentialRequestLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialResponse_checkValidContents(const uint8_t *profileKeyCredentialResponse,
|
||||
uint32_t profileKeyCredentialResponseLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredential_checkValidContents(const uint8_t *profileKeyCredential,
|
||||
uint32_t profileKeyCredentialLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialPresentation_checkValidContents(const uint8_t *profileKeyCredentialPresentation,
|
||||
uint32_t profileKeyCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialPresentation_getUuidCiphertext(const uint8_t *profileKeyCredentialPresentation,
|
||||
uint32_t profileKeyCredentialPresentationLen,
|
||||
uint8_t *uuidCiphertextOut,
|
||||
uint32_t uuidCiphertextLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCredentialPresentation_getProfileKeyCiphertext(const uint8_t *profileKeyCredentialPresentation,
|
||||
uint32_t profileKeyCredentialPresentationLen,
|
||||
uint8_t *profileKeyCiphertextOut,
|
||||
uint32_t profileKeyCiphertextLen);
|
||||
|
||||
int32_t FFI_ReceiptCredentialRequestContext_checkValidContents(const uint8_t *receiptCredentialRequestContext,
|
||||
uint32_t receiptCredentialRequestContextLen);
|
||||
|
||||
int32_t FFI_ReceiptCredentialRequestContext_getRequest(const uint8_t *receiptCredentialRequestContext,
|
||||
uint32_t receiptCredentialRequestContextLen,
|
||||
uint8_t *receiptCredentialRequestOut,
|
||||
uint32_t receiptCredentialRequestLen);
|
||||
|
||||
int32_t FFI_ReceiptCredentialRequest_checkValidContents(const uint8_t *receiptCredentialRequest,
|
||||
uint32_t receiptCredentialRequestLen);
|
||||
|
||||
int32_t FFI_ReceiptCredentialResponse_checkValidContents(const uint8_t *receiptCredentialResponse,
|
||||
uint32_t receiptCredentialResponseLen);
|
||||
|
||||
int32_t FFI_ReceiptCredential_checkValidContents(const uint8_t *receiptCredential,
|
||||
uint32_t receiptCredentialLen);
|
||||
|
||||
int32_t FFI_ReceiptCredential_getReceiptExpirationTime(const uint8_t *receiptCredential,
|
||||
uint32_t receiptCredentialLen,
|
||||
uint8_t *receiptExpirationTimeOut,
|
||||
uint32_t receiptExpirationTimeLen);
|
||||
|
||||
int32_t FFI_ReceiptCredential_getReceiptLevel(const uint8_t *receiptCredential,
|
||||
uint32_t receiptCredentialLen,
|
||||
uint8_t *receiptLevelOut,
|
||||
uint32_t receiptLevelLen);
|
||||
|
||||
int32_t FFI_ReceiptCredentialPresentation_checkValidContents(const uint8_t *receiptCredentialPresentation,
|
||||
uint32_t receiptCredentialPresentationLen);
|
||||
|
||||
int32_t FFI_UuidCiphertext_checkValidContents(const uint8_t *uuidCiphertext,
|
||||
uint32_t uuidCiphertextLen);
|
||||
|
||||
int32_t FFI_ProfileKeyCiphertext_checkValidContents(const uint8_t *profileKeyCiphertext,
|
||||
uint32_t profileKeyCiphertextLen);
|
||||
|
||||
int32_t FFI_Randomness_checkValidContents(const uint8_t *randomness, uint32_t randomnessLen);
|
||||
|
||||
int32_t FFI_Uuid_checkValidContents(const uint8_t *uuid, uint32_t uuidLen);
|
||||
@ -1,16 +0,0 @@
|
||||
|
||||
.PHONY: native_library
|
||||
.PHONY: jar
|
||||
.PHONY: test
|
||||
|
||||
native_library:
|
||||
cargo build --release
|
||||
cp ../../target/release/libzkgroup.so src/main/resources/ 2>/dev/null || \
|
||||
cp ../../target/release/libzkgroup.dylib src/main/resources/
|
||||
|
||||
jar:
|
||||
mvn package
|
||||
|
||||
test:
|
||||
mvn test
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
plugins {
|
||||
id "de.undercouch.download" version "4.1.1"
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply from: '../../deploy.gradle'
|
||||
|
||||
archivesBaseName = 'zkgroup-java'
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.mockito:mockito-core:1.9.5'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
otherPlatformLibraries {}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn ':makeServer'
|
||||
}
|
||||
|
||||
tasks.withType(AbstractArchiveTask) {
|
||||
preserveFileTimestamps = false
|
||||
reproducibleFileOrder = true
|
||||
}
|
||||
|
||||
jar {
|
||||
dependsOn ':makeServer'
|
||||
}
|
||||
|
||||
test {
|
||||
// Test against the .jar file from build/libs
|
||||
dependsOn 'jar'
|
||||
classpath = sourceSets.test.runtimeClasspath - files("build/classes/java/main") - files("build/resources/main") + fileTree(dir:"build/libs")
|
||||
}
|
||||
|
||||
task packageJavadoc(type: Jar, dependsOn: 'javadoc') {
|
||||
from javadoc.destinationDir
|
||||
classifier = 'javadoc'
|
||||
}
|
||||
|
||||
task packageSources(type: Jar) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
|
||||
task testableJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
from sourceSets.otherPlatformLibraries.resources
|
||||
classifier = 'testable'
|
||||
|
||||
def extraResources = ['libzkgroup.dll', 'libzkgroup.dylib']
|
||||
def extraResourcesDir = 'src/otherPlatformLibraries/resources'
|
||||
|
||||
doFirst {
|
||||
mkdir extraResourcesDir
|
||||
extraResources.each { name ->
|
||||
def artifact = name.replace('libzkgroup', 'libzkgroup-x64')
|
||||
download {
|
||||
src 'https://github.com/signalapp/zkgroup/releases/download/v' + project.version + '/' + artifact
|
||||
dest extraResourcesDir + '/' + name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives packageJavadoc
|
||||
archives packageSources
|
||||
archives testableJar
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
public class InvalidInputException extends Exception {
|
||||
|
||||
public InvalidInputException() {
|
||||
|
||||
}
|
||||
|
||||
public InvalidInputException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
package org.signal.zkgroup;
|
||||
|
||||
public class InvalidRedemptionTimeException extends Exception {
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
|
||||
public final class NotarySignature extends ByteArray {
|
||||
|
||||
public static final int SIZE = 64;
|
||||
|
||||
public NotarySignature(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ServerPublicParams extends ByteArray {
|
||||
|
||||
public static final int SIZE = 225;
|
||||
|
||||
public ServerPublicParams(byte[] contents) {
|
||||
super(contents, SIZE, true);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public void verifySignature(byte[] message, NotarySignature notarySignature) throws VerificationFailedException {
|
||||
int ffi_return = Native.serverPublicParamsVerifySignatureJNI(contents, message, notarySignature.getInternalContentsForJNI());
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ServerSecretParams extends ByteArray {
|
||||
|
||||
public static final int SIZE = 1121;
|
||||
|
||||
public static ServerSecretParams generate() {
|
||||
return generate(new SecureRandom());
|
||||
}
|
||||
|
||||
public static ServerSecretParams generate(SecureRandom secureRandom) {
|
||||
byte[] newContents = new byte[ServerSecretParams.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsGenerateDeterministicJNI(random, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ServerSecretParams(newContents);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ServerSecretParams(byte[] contents) {
|
||||
super(contents, SIZE, true);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public ServerPublicParams getPublicParams() {
|
||||
byte[] newContents = new byte[ServerPublicParams.SIZE];
|
||||
|
||||
int ffi_return = Native.serverSecretParamsGetPublicParamsJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return new ServerPublicParams(newContents);
|
||||
}
|
||||
|
||||
public NotarySignature sign(byte[] message) {
|
||||
return sign(new SecureRandom(), message);
|
||||
}
|
||||
|
||||
public NotarySignature sign(SecureRandom secureRandom, byte[] message) {
|
||||
byte[] newContents = new byte[NotarySignature.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsSignDeterministicJNI(contents, random, message, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new NotarySignature(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
public class VerificationFailedException extends Exception {
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
package org.signal.zkgroup;
|
||||
|
||||
public final class ZkGroupError extends Error {
|
||||
|
||||
public ZkGroupError(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.auth;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class AuthCredential extends ByteArray {
|
||||
|
||||
public static final int SIZE = 181;
|
||||
|
||||
public AuthCredential(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.authCredentialCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.auth;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.UuidCiphertext;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class AuthCredentialPresentation extends ByteArray {
|
||||
|
||||
public static final int SIZE = 493;
|
||||
|
||||
public AuthCredentialPresentation(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.authCredentialPresentationCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public UuidCiphertext getUuidCiphertext() {
|
||||
byte[] newContents = new byte[UuidCiphertext.SIZE];
|
||||
|
||||
int ffi_return = Native.authCredentialPresentationGetUuidCiphertextJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new UuidCiphertext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getRedemptionTime() {
|
||||
byte[] newContents = new byte[4];
|
||||
|
||||
int ffi_return = Native.authCredentialPresentationGetRedemptionTimeJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return ByteBuffer.wrap(newContents).getInt();
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.auth;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class AuthCredentialResponse extends ByteArray {
|
||||
|
||||
public static final int SIZE = 361;
|
||||
|
||||
public AuthCredentialResponse(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.authCredentialResponseCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.auth;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerPublicParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public class ClientZkAuthOperations {
|
||||
|
||||
private final ServerPublicParams serverPublicParams;
|
||||
|
||||
public ClientZkAuthOperations(ServerPublicParams serverPublicParams) {
|
||||
this.serverPublicParams = serverPublicParams;
|
||||
}
|
||||
|
||||
public AuthCredential receiveAuthCredential(UUID uuid, int redemptionTime, AuthCredentialResponse authCredentialResponse) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[AuthCredential.SIZE];
|
||||
|
||||
int ffi_return = Native.serverPublicParamsReceiveAuthCredentialJNI(serverPublicParams.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), redemptionTime, authCredentialResponse.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new AuthCredential(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public AuthCredentialPresentation createAuthCredentialPresentation(GroupSecretParams groupSecretParams, AuthCredential authCredential) {
|
||||
return createAuthCredentialPresentation(new SecureRandom(), groupSecretParams, authCredential);
|
||||
}
|
||||
|
||||
public AuthCredentialPresentation createAuthCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, AuthCredential authCredential) {
|
||||
byte[] newContents = new byte[AuthCredentialPresentation.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCreateAuthCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), authCredential.getInternalContentsForJNI(), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new AuthCredentialPresentation(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,78 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.auth;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerSecretParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.InvalidRedemptionTimeException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.GroupPublicParams;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public class ServerZkAuthOperations {
|
||||
|
||||
private final ServerSecretParams serverSecretParams;
|
||||
|
||||
public ServerZkAuthOperations(ServerSecretParams serverSecretParams) {
|
||||
this.serverSecretParams = serverSecretParams;
|
||||
}
|
||||
|
||||
public AuthCredentialResponse issueAuthCredential(UUID uuid, int redemptionTime) {
|
||||
return issueAuthCredential(new SecureRandom(), uuid, redemptionTime);
|
||||
}
|
||||
|
||||
public AuthCredentialResponse issueAuthCredential(SecureRandom secureRandom, UUID uuid, int redemptionTime) {
|
||||
byte[] newContents = new byte[AuthCredentialResponse.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsIssueAuthCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, UUIDUtil.serialize(uuid), redemptionTime, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new AuthCredentialResponse(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation) throws VerificationFailedException, InvalidRedemptionTimeException {
|
||||
verifyAuthCredentialPresentation(groupPublicParams, authCredentialPresentation, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation, long currentTimeMillis) throws VerificationFailedException, InvalidRedemptionTimeException {
|
||||
long acceptableStartTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()-1, TimeUnit.DAYS);
|
||||
long acceptableEndTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()+2, TimeUnit.DAYS);
|
||||
|
||||
if (currentTimeMillis < acceptableStartTime || currentTimeMillis > acceptableEndTime) {
|
||||
throw new InvalidRedemptionTimeException();
|
||||
}
|
||||
|
||||
int ffi_return = Native.serverSecretParamsVerifyAuthCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), authCredentialPresentation.getInternalContentsForJNI());
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public class ClientZkGroupCipher {
|
||||
|
||||
private final GroupSecretParams groupSecretParams;
|
||||
|
||||
public ClientZkGroupCipher(GroupSecretParams groupSecretParams) {
|
||||
this.groupSecretParams = groupSecretParams;
|
||||
}
|
||||
|
||||
public UuidCiphertext encryptUuid(UUID uuid) {
|
||||
byte[] newContents = new byte[UuidCiphertext.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsEncryptUuidJNI(groupSecretParams.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new UuidCiphertext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public UUID decryptUuid(UuidCiphertext uuidCiphertext) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[UUIDUtil.UUID_LENGTH];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsDecryptUuidJNI(groupSecretParams.getInternalContentsForJNI(), uuidCiphertext.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return UUIDUtil.deserialize(newContents);
|
||||
}
|
||||
|
||||
public ProfileKeyCiphertext encryptProfileKey(ProfileKey profileKey, UUID uuid) {
|
||||
byte[] newContents = new byte[ProfileKeyCiphertext.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsEncryptProfileKeyJNI(groupSecretParams.getInternalContentsForJNI(), profileKey.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCiphertext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProfileKey decryptProfileKey(ProfileKeyCiphertext profileKeyCiphertext, UUID uuid) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ProfileKey.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsDecryptProfileKeyJNI(groupSecretParams.getInternalContentsForJNI(), profileKeyCiphertext.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKey(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] encryptBlob(byte[] plaintext) throws VerificationFailedException {
|
||||
return encryptBlob(new SecureRandom(), plaintext);
|
||||
}
|
||||
|
||||
public byte[] encryptBlob(SecureRandom secureRandom, byte[] plaintext) throws VerificationFailedException {
|
||||
|
||||
byte[] paddedPlaintext = new byte[plaintext.length + 4];
|
||||
System.arraycopy(plaintext, 0, paddedPlaintext, 4, plaintext.length);
|
||||
|
||||
byte[] newContents = new byte[paddedPlaintext.length+29];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.groupSecretParamsEncryptBlobDeterministicJNI(groupSecretParams.getInternalContentsForJNI(), random, paddedPlaintext, newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return newContents;
|
||||
}
|
||||
|
||||
public byte[] decryptBlob(byte[] blobCiphertext) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[blobCiphertext.length-29];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsDecryptBlobJNI(groupSecretParams.getInternalContentsForJNI(), blobCiphertext, newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
if (newContents.length < 4) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
byte[] padLenBytes = new byte[4];
|
||||
System.arraycopy(newContents, 0, padLenBytes, 0, 4);
|
||||
int padLen = ByteBuffer.wrap(newContents).getInt();
|
||||
if (newContents.length < (4 + padLen)) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
byte[] depaddedContents = new byte[newContents.length - (4 + padLen)];
|
||||
System.arraycopy(newContents, 4, depaddedContents, 0, newContents.length - (4 + padLen));
|
||||
|
||||
return depaddedContents;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
|
||||
public final class GroupIdentifier extends ByteArray {
|
||||
|
||||
public static final int SIZE = 32;
|
||||
|
||||
public GroupIdentifier(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
|
||||
public final class GroupMasterKey extends ByteArray {
|
||||
|
||||
public static final int SIZE = 32;
|
||||
|
||||
public GroupMasterKey(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class GroupPublicParams extends ByteArray {
|
||||
|
||||
public static final int SIZE = 97;
|
||||
|
||||
public GroupPublicParams(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.groupPublicParamsCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public GroupIdentifier getGroupIdentifier() {
|
||||
byte[] newContents = new byte[GroupIdentifier.SIZE];
|
||||
|
||||
int ffi_return = Native.groupPublicParamsGetGroupIdentifierJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new GroupIdentifier(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class GroupSecretParams extends ByteArray {
|
||||
|
||||
public static final int SIZE = 289;
|
||||
|
||||
public static GroupSecretParams generate() {
|
||||
return generate(new SecureRandom());
|
||||
}
|
||||
|
||||
public static GroupSecretParams generate(SecureRandom secureRandom) {
|
||||
byte[] newContents = new byte[GroupSecretParams.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.groupSecretParamsGenerateDeterministicJNI(random, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new GroupSecretParams(newContents);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static GroupSecretParams deriveFromMasterKey(GroupMasterKey groupMasterKey) {
|
||||
byte[] newContents = new byte[GroupSecretParams.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsDeriveFromMasterKeyJNI(groupMasterKey.getInternalContentsForJNI(), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new GroupSecretParams(newContents);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public GroupSecretParams(byte[] contents) {
|
||||
super(contents, SIZE, true);
|
||||
|
||||
int ffi_return = Native.groupSecretParamsCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public GroupMasterKey getMasterKey() {
|
||||
byte[] newContents = new byte[GroupMasterKey.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsGetMasterKeyJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new GroupMasterKey(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GroupPublicParams getPublicParams() {
|
||||
byte[] newContents = new byte[GroupPublicParams.SIZE];
|
||||
|
||||
int ffi_return = Native.groupSecretParamsGetPublicParamsJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new GroupPublicParams(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCiphertext extends ByteArray {
|
||||
|
||||
public static final int SIZE = 65;
|
||||
|
||||
public ProfileKeyCiphertext(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCiphertextCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.groups;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class UuidCiphertext extends ByteArray {
|
||||
|
||||
public static final int SIZE = 65;
|
||||
|
||||
public UuidCiphertext(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.uuidCiphertextCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
package org.signal.zkgroup.internal;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class ByteArray {
|
||||
|
||||
protected final byte[] contents;
|
||||
|
||||
protected ByteArray(byte[] contents, int expectedLength) throws InvalidInputException {
|
||||
this.contents = cloneArrayOfLength(contents, expectedLength);
|
||||
}
|
||||
|
||||
protected ByteArray(byte[] contents, int expectedLength, boolean unrecoverable) {
|
||||
try {
|
||||
this.contents = cloneArrayOfLength(contents, expectedLength);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] cloneArrayOfLength(byte[] bytes, int expectedLength) throws InvalidInputException {
|
||||
if (bytes.length != expectedLength) {
|
||||
throw new InvalidInputException(String.format(Locale.US, "Length of array supplied was %d expected %d", bytes.length, expectedLength));
|
||||
}
|
||||
|
||||
return bytes.clone();
|
||||
}
|
||||
|
||||
public byte[] getInternalContentsForJNI() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode() * 31 + Arrays.hashCode(contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ByteArray other = (ByteArray) o;
|
||||
if (contents == other.contents) return true;
|
||||
|
||||
if (contents.length != other.contents.length) return false;
|
||||
|
||||
int result = 0;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
result |= contents[i] ^ other.contents[i];
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.internal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public final class Native {
|
||||
|
||||
public static final int FFI_RETURN_OK = 0;
|
||||
public static final int FFI_RETURN_INTERNAL_ERROR = 1; // ZkGroupError
|
||||
public static final int FFI_RETURN_INPUT_ERROR = 2;
|
||||
|
||||
public static final int RANDOM_LENGTH = 32;
|
||||
|
||||
static {
|
||||
try {
|
||||
String osName = System.getProperty("os.name").toLowerCase(java.util.Locale.ROOT);
|
||||
boolean isMacOs = osName.startsWith("mac os x");
|
||||
String extension = isMacOs ? ".dylib" : ".so";
|
||||
|
||||
try (InputStream in = Native.class.getResourceAsStream("/libzkgroup" + extension)) {
|
||||
if (in != null) {
|
||||
copyToTempFileAndLoad(in, extension);
|
||||
} else {
|
||||
System.loadLibrary("zkgroup");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Native() {
|
||||
}
|
||||
|
||||
private static void copyToTempFileAndLoad(InputStream in, String extension) throws IOException {
|
||||
File tempFile = Files.createTempFile("resource", extension).toFile();
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
try (OutputStream out = new FileOutputStream(tempFile)) {
|
||||
|
||||
copy(in, out);
|
||||
}
|
||||
System.load(tempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static native int profileKeyGetCommitmentJNI(byte[] self, byte[] uuid, byte[] output);
|
||||
public static native int profileKeyGetProfileKeyVersionJNI(byte[] self, byte[] uuid, byte[] output);
|
||||
public static native int profileKeyCommitmentCheckValidContentsJNI(byte[] self);
|
||||
public static native int groupSecretParamsGenerateDeterministicJNI(byte[] randomness, byte[] output);
|
||||
public static native int groupSecretParamsDeriveFromMasterKeyJNI(byte[] groupMasterKey, byte[] output);
|
||||
public static native int groupSecretParamsGetMasterKeyJNI(byte[] self, byte[] output);
|
||||
public static native int groupSecretParamsGetPublicParamsJNI(byte[] self, byte[] output);
|
||||
public static native int groupSecretParamsCheckValidContentsJNI(byte[] self);
|
||||
public static native int groupSecretParamsEncryptUuidJNI(byte[] self, byte[] uuid, byte[] output);
|
||||
public static native int groupSecretParamsDecryptUuidJNI(byte[] self, byte[] uuidCiphertext, byte[] output);
|
||||
public static native int groupSecretParamsEncryptProfileKeyJNI(byte[] self, byte[] profileKey, byte[] uuid, byte[] output);
|
||||
public static native int groupSecretParamsDecryptProfileKeyJNI(byte[] self, byte[] profileKeyCiphertext, byte[] uuid, byte[] output);
|
||||
public static native int groupSecretParamsEncryptBlobDeterministicJNI(byte[] self, byte[] randomness, byte[] plaintext, byte[] output);
|
||||
public static native int groupSecretParamsDecryptBlobJNI(byte[] self, byte[] blobCiphertext, byte[] output);
|
||||
public static native int serverSecretParamsGenerateDeterministicJNI(byte[] randomness, byte[] output);
|
||||
public static native int serverSecretParamsGetPublicParamsJNI(byte[] self, byte[] output);
|
||||
public static native int serverSecretParamsSignDeterministicJNI(byte[] self, byte[] randomness, byte[] message, byte[] output);
|
||||
public static native int serverSecretParamsCheckValidContentsJNI(byte[] self);
|
||||
public static native int serverPublicParamsReceiveAuthCredentialJNI(byte[] self, byte[] uuid, int redemptionTime, byte[] authCredentialResponse, byte[] output);
|
||||
public static native int serverPublicParamsCreateAuthCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] groupSecretParams, byte[] authCredential, byte[] output);
|
||||
public static native int serverPublicParamsCreateProfileKeyCredentialRequestContextDeterministicJNI(byte[] self, byte[] randomness, byte[] uuid, byte[] profileKey, byte[] output);
|
||||
public static native int serverPublicParamsReceiveProfileKeyCredentialJNI(byte[] self, byte[] profileKeyCredentialRequestContext, byte[] profileKeyCredentialResponse, byte[] output);
|
||||
public static native int serverPublicParamsCreateProfileKeyCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] groupSecretParams, byte[] profileKeyCredential, byte[] output);
|
||||
public static native int serverPublicParamsCreateReceiptCredentialRequestContextDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptSerial, byte[] output);
|
||||
public static native int serverPublicParamsReceiveReceiptCredentialJNI(byte[] self, byte[] receiptCredentialRequestContext, byte[] receiptCredentialResponse, byte[] output);
|
||||
public static native int serverPublicParamsCreateReceiptCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptCredential, byte[] output);
|
||||
public static native int serverSecretParamsIssueAuthCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] uuid, int redemptionTime, byte[] output);
|
||||
public static native int serverSecretParamsVerifyAuthCredentialPresentationJNI(byte[] self, byte[] groupPublicParams, byte[] authCredentialPresentation);
|
||||
public static native int serverSecretParamsIssueProfileKeyCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] profileKeyCredentialRequest, byte[] uuid, byte[] profileKeyCommitment, byte[] output);
|
||||
public static native int serverSecretParamsVerifyProfileKeyCredentialPresentationJNI(byte[] self, byte[] groupPublicParams, byte[] profileKeyCredentialPresentation);
|
||||
public static native int serverSecretParamsIssueReceiptCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptCredentialRequest, long receiptExpirationTime, long receiptLevel, byte[] output);
|
||||
public static native int serverSecretParamsVerifyReceiptCredentialPresentationJNI(byte[] self, byte[] receiptCredentialPresentation);
|
||||
public static native int groupPublicParamsGetGroupIdentifierJNI(byte[] self, byte[] output);
|
||||
public static native int groupPublicParamsCheckValidContentsJNI(byte[] self);
|
||||
public static native int serverPublicParamsVerifySignatureJNI(byte[] self, byte[] message, byte[] notarySignature);
|
||||
public static native int serverPublicParamsCheckValidContentsJNI(byte[] self);
|
||||
public static native int authCredentialResponseCheckValidContentsJNI(byte[] self);
|
||||
public static native int authCredentialCheckValidContentsJNI(byte[] self);
|
||||
public static native int authCredentialPresentationGetUuidCiphertextJNI(byte[] self, byte[] output);
|
||||
public static native int authCredentialPresentationGetRedemptionTimeJNI(byte[] self, byte[] output);
|
||||
public static native int authCredentialPresentationCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCredentialRequestContextGetRequestJNI(byte[] self, byte[] output);
|
||||
public static native int profileKeyCredentialRequestContextCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCredentialRequestCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCredentialResponseCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCredentialCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCredentialPresentationGetUuidCiphertextJNI(byte[] self, byte[] output);
|
||||
public static native int profileKeyCredentialPresentationGetProfileKeyCiphertextJNI(byte[] self, byte[] output);
|
||||
public static native int profileKeyCredentialPresentationCheckValidContentsJNI(byte[] self);
|
||||
public static native int receiptCredentialRequestContextGetRequestJNI(byte[] self, byte[] output);
|
||||
public static native int receiptCredentialRequestContextCheckValidContentsJNI(byte[] self);
|
||||
public static native int receiptCredentialRequestCheckValidContentsJNI(byte[] self);
|
||||
public static native int receiptCredentialResponseCheckValidContentsJNI(byte[] self);
|
||||
public static native int receiptCredentialGetReceiptExpirationTimeJNI(byte[] self, byte[] output);
|
||||
public static native int receiptCredentialGetReceiptLevelJNI(byte[] self, byte[] output);
|
||||
public static native int receiptCredentialCheckValidContentsJNI(byte[] self);
|
||||
public static native int receiptCredentialPresentationCheckValidContentsJNI(byte[] self);
|
||||
public static native int uuidCiphertextCheckValidContentsJNI(byte[] self);
|
||||
public static native int profileKeyCiphertextCheckValidContentsJNI(byte[] self);
|
||||
|
||||
private static void copy(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,102 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerPublicParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public class ClientZkProfileOperations {
|
||||
|
||||
private final ServerPublicParams serverPublicParams;
|
||||
|
||||
public ClientZkProfileOperations(ServerPublicParams serverPublicParams) {
|
||||
this.serverPublicParams = serverPublicParams;
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(UUID uuid, ProfileKey profileKey) {
|
||||
return createProfileKeyCredentialRequestContext(new SecureRandom(), uuid, profileKey);
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(SecureRandom secureRandom, UUID uuid, ProfileKey profileKey) {
|
||||
byte[] newContents = new byte[ProfileKeyCredentialRequestContext.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCreateProfileKeyCredentialRequestContextDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, UUIDUtil.serialize(uuid), profileKey.getInternalContentsForJNI(), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCredentialRequestContext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProfileKeyCredential receiveProfileKeyCredential(ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext, ProfileKeyCredentialResponse profileKeyCredentialResponse) throws VerificationFailedException {
|
||||
if (profileKeyCredentialResponse == null) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
byte[] newContents = new byte[ProfileKeyCredential.SIZE];
|
||||
|
||||
int ffi_return = Native.serverPublicParamsReceiveProfileKeyCredentialJNI(serverPublicParams.getInternalContentsForJNI(), profileKeyCredentialRequestContext.getInternalContentsForJNI(), profileKeyCredentialResponse.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCredential(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(GroupSecretParams groupSecretParams, ProfileKeyCredential profileKeyCredential) {
|
||||
return createProfileKeyCredentialPresentation(new SecureRandom(), groupSecretParams, profileKeyCredential);
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, ProfileKeyCredential profileKeyCredential) {
|
||||
byte[] newContents = new byte[ProfileKeyCredentialPresentation.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCreateProfileKeyCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), profileKeyCredential.getInternalContentsForJNI(), newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCredentialPresentation(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public final class ProfileKey extends ByteArray {
|
||||
|
||||
public static final int SIZE = 32;
|
||||
|
||||
public ProfileKey(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public ProfileKeyCommitment getCommitment(UUID uuid) {
|
||||
byte[] newContents = new byte[ProfileKeyCommitment.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyGetCommitmentJNI(contents, UUIDUtil.serialize(uuid), newContents);
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCommitment(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProfileKeyVersion getProfileKeyVersion(UUID uuid) {
|
||||
byte[] newContents = new byte[ProfileKeyVersion.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyGetProfileKeyVersionJNI(contents, UUIDUtil.serialize(uuid), newContents);
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyVersion(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCommitment extends ByteArray {
|
||||
|
||||
public static final int SIZE = 97;
|
||||
|
||||
public ProfileKeyCommitment(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCommitmentCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCredential extends ByteArray {
|
||||
|
||||
public static final int SIZE = 145;
|
||||
|
||||
public ProfileKeyCredential(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.ProfileKeyCiphertext;
|
||||
import org.signal.zkgroup.groups.UuidCiphertext;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCredentialPresentation extends ByteArray {
|
||||
|
||||
public static final int SIZE = 713;
|
||||
|
||||
public ProfileKeyCredentialPresentation(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialPresentationCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public UuidCiphertext getUuidCiphertext() {
|
||||
byte[] newContents = new byte[UuidCiphertext.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialPresentationGetUuidCiphertextJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new UuidCiphertext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProfileKeyCiphertext getProfileKeyCiphertext() {
|
||||
byte[] newContents = new byte[ProfileKeyCiphertext.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialPresentationGetProfileKeyCiphertextJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCiphertext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCredentialRequest extends ByteArray {
|
||||
|
||||
public static final int SIZE = 329;
|
||||
|
||||
public ProfileKeyCredentialRequest(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialRequestCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCredentialRequestContext extends ByteArray {
|
||||
|
||||
public static final int SIZE = 473;
|
||||
|
||||
public ProfileKeyCredentialRequestContext(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialRequestContextCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialRequest getRequest() {
|
||||
byte[] newContents = new byte[ProfileKeyCredentialRequest.SIZE];
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialRequestContextGetRequestJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCredentialRequest(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ProfileKeyCredentialResponse extends ByteArray {
|
||||
|
||||
public static final int SIZE = 457;
|
||||
|
||||
public ProfileKeyCredentialResponse(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.profileKeyCredentialResponseCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public final class ProfileKeyVersion extends ByteArray {
|
||||
|
||||
public static final int SIZE = 64;
|
||||
|
||||
public ProfileKeyVersion(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public ProfileKeyVersion(String contents) throws InvalidInputException, UnsupportedEncodingException {
|
||||
super(contents.getBytes("UTF-8"), SIZE);
|
||||
}
|
||||
|
||||
public String serialize() {
|
||||
try {
|
||||
return new String(contents, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.profiles;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerSecretParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.groups.GroupPublicParams;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
import org.signal.zkgroup.util.UUIDUtil;
|
||||
|
||||
public class ServerZkProfileOperations {
|
||||
|
||||
private final ServerSecretParams serverSecretParams;
|
||||
|
||||
public ServerZkProfileOperations(ServerSecretParams serverSecretParams) {
|
||||
this.serverSecretParams = serverSecretParams;
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialResponse issueProfileKeyCredential(ProfileKeyCredentialRequest profileKeyCredentialRequest, UUID uuid, ProfileKeyCommitment profileKeyCommitment) throws VerificationFailedException {
|
||||
return issueProfileKeyCredential(new SecureRandom(), profileKeyCredentialRequest, uuid, profileKeyCommitment);
|
||||
}
|
||||
|
||||
public ProfileKeyCredentialResponse issueProfileKeyCredential(SecureRandom secureRandom, ProfileKeyCredentialRequest profileKeyCredentialRequest, UUID uuid, ProfileKeyCommitment profileKeyCommitment) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ProfileKeyCredentialResponse.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsIssueProfileKeyCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, profileKeyCredentialRequest.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), profileKeyCommitment.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ProfileKeyCredentialResponse(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void verifyProfileKeyCredentialPresentation(GroupPublicParams groupPublicParams, ProfileKeyCredentialPresentation profileKeyCredentialPresentation) throws VerificationFailedException {
|
||||
int ffi_return = Native.serverSecretParamsVerifyProfileKeyCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), profileKeyCredentialPresentation.getInternalContentsForJNI());
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerPublicParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public class ClientZkReceiptOperations {
|
||||
|
||||
private final ServerPublicParams serverPublicParams;
|
||||
|
||||
public ClientZkReceiptOperations(ServerPublicParams serverPublicParams) {
|
||||
this.serverPublicParams = serverPublicParams;
|
||||
}
|
||||
|
||||
public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(ReceiptSerial receiptSerial) throws VerificationFailedException {
|
||||
return createReceiptCredentialRequestContext(new SecureRandom(), receiptSerial);
|
||||
}
|
||||
|
||||
public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(SecureRandom secureRandom, ReceiptSerial receiptSerial) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ReceiptCredentialRequestContext.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCreateReceiptCredentialRequestContextDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, receiptSerial.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ReceiptCredentialRequestContext(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ReceiptCredential receiveReceiptCredential(ReceiptCredentialRequestContext receiptCredentialRequestContext, ReceiptCredentialResponse receiptCredentialResponse) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ReceiptCredential.SIZE];
|
||||
|
||||
int ffi_return = Native.serverPublicParamsReceiveReceiptCredentialJNI(serverPublicParams.getInternalContentsForJNI(), receiptCredentialRequestContext.getInternalContentsForJNI(), receiptCredentialResponse.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ReceiptCredential(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ReceiptCredentialPresentation createReceiptCredentialPresentation(ReceiptCredential receiptCredential) throws VerificationFailedException {
|
||||
return createReceiptCredentialPresentation(new SecureRandom(), receiptCredential);
|
||||
}
|
||||
|
||||
public ReceiptCredentialPresentation createReceiptCredentialPresentation(SecureRandom secureRandom, ReceiptCredential receiptCredential) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ReceiptCredentialPresentation.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverPublicParamsCreateReceiptCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, receiptCredential.getInternalContentsForJNI(), newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ReceiptCredentialPresentation(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ReceiptCredential extends ByteArray {
|
||||
|
||||
public static final int SIZE = 129;
|
||||
|
||||
public ReceiptCredential(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.receiptCredentialCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public long getReceiptExpirationTime() {
|
||||
byte[] newContents = new byte[8];
|
||||
|
||||
int ffi_return = Native.receiptCredentialGetReceiptExpirationTimeJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return ByteBuffer.wrap(newContents).getLong();
|
||||
}
|
||||
|
||||
public long getReceiptLevel() {
|
||||
byte[] newContents = new byte[8];
|
||||
|
||||
int ffi_return = Native.receiptCredentialGetReceiptLevelJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
return ByteBuffer.wrap(newContents).getLong();
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ReceiptCredentialPresentation extends ByteArray {
|
||||
|
||||
public static final int SIZE = 329;
|
||||
|
||||
public ReceiptCredentialPresentation(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.receiptCredentialPresentationCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ReceiptCredentialRequest extends ByteArray {
|
||||
|
||||
public static final int SIZE = 97;
|
||||
|
||||
public ReceiptCredentialRequest(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.receiptCredentialRequestCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ReceiptCredentialRequestContext extends ByteArray {
|
||||
|
||||
public static final int SIZE = 177;
|
||||
|
||||
public ReceiptCredentialRequestContext(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.receiptCredentialRequestContextCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public ReceiptCredentialRequest getRequest() {
|
||||
byte[] newContents = new byte[ReceiptCredentialRequest.SIZE];
|
||||
|
||||
int ffi_return = Native.receiptCredentialRequestContextGetRequestJNI(contents, newContents);
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ReceiptCredentialRequest(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public final class ReceiptCredentialResponse extends ByteArray {
|
||||
|
||||
public static final int SIZE = 409;
|
||||
|
||||
public ReceiptCredentialResponse(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
|
||||
int ffi_return = Native.receiptCredentialResponseCheckValidContentsJNI(contents);
|
||||
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.internal.ByteArray;
|
||||
|
||||
public final class ReceiptSerial extends ByteArray {
|
||||
|
||||
public static final int SIZE = 16;
|
||||
|
||||
public ReceiptSerial(byte[] contents) throws InvalidInputException {
|
||||
super(contents, SIZE);
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return contents.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2020 Signal Messenger, LLC.
|
||||
// All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
//
|
||||
|
||||
// Generated by zkgroup/codegen/codegen.py - do not edit
|
||||
|
||||
package org.signal.zkgroup.receipts;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.ServerSecretParams;
|
||||
import org.signal.zkgroup.VerificationFailedException;
|
||||
import org.signal.zkgroup.ZkGroupError;
|
||||
import org.signal.zkgroup.internal.Native;
|
||||
|
||||
public class ServerZkReceiptOperations {
|
||||
|
||||
private final ServerSecretParams serverSecretParams;
|
||||
|
||||
public ServerZkReceiptOperations(ServerSecretParams serverSecretParams) {
|
||||
this.serverSecretParams = serverSecretParams;
|
||||
}
|
||||
|
||||
public ReceiptCredentialResponse issueReceiptCredential(ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
|
||||
return issueReceiptCredential(new SecureRandom(), receiptCredentialRequest, receiptExpirationTime, receiptLevel);
|
||||
}
|
||||
|
||||
public ReceiptCredentialResponse issueReceiptCredential(SecureRandom secureRandom, ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
|
||||
byte[] newContents = new byte[ReceiptCredentialResponse.SIZE];
|
||||
byte[] random = new byte[Native.RANDOM_LENGTH];
|
||||
|
||||
secureRandom.nextBytes(random);
|
||||
|
||||
int ffi_return = Native.serverSecretParamsIssueReceiptCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, receiptCredentialRequest.getInternalContentsForJNI(), receiptExpirationTime, receiptLevel, newContents);
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
|
||||
try {
|
||||
return new ReceiptCredentialResponse(newContents);
|
||||
} catch (InvalidInputException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void verifyReceiptCredentialPresentation(ReceiptCredentialPresentation receiptCredentialPresentation) throws VerificationFailedException {
|
||||
int ffi_return = Native.serverSecretParamsVerifyReceiptCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), receiptCredentialPresentation.getInternalContentsForJNI());
|
||||
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
|
||||
throw new VerificationFailedException();
|
||||
}
|
||||
|
||||
if (ffi_return != Native.FFI_RETURN_OK) {
|
||||
throw new ZkGroupError("FFI_RETURN!=OK");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||