├── LICENSE ├── README.md ├── android ├── .gitignore ├── .idea │ ├── .name │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── punchcard │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── punchcard │ │ │ │ ├── MainActivity.java │ │ │ │ └── RustPunchCard.java │ │ ├── jniLibs │ │ │ ├── arm64 │ │ │ │ └── libcargo.so │ │ │ ├── armeabi │ │ │ │ └── libcargo.so │ │ │ └── x86 │ │ │ │ └── libcargo.so │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── punchcard │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── build.sh ├── cargo-config.toml ├── cargo ├── .gitignore ├── Cargo.lock ├── Cargo.toml └── src │ ├── bin.rs │ ├── crypto.rs │ ├── crypto_pairing.rs │ ├── lib.rs │ └── lib │ ├── crypto.rs │ └── crypto_pairing.rs └── data.txt /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Saba Eskandarian 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This code accompanies the paper "Fast Privacy-Preserving Punch Cards" (https://eprint.iacr.org/2020/741.pdf) 2 | 3 | `data.txt` contains the evaluation results that appear in the paper. The performance numbers labeled "computer" were taken on a laptop with an intel i5-8265U processer @ 1.60 GHz running Ubuntu Linux. The "Google Pixel" numbers were measured on the Google Pixel (first generation) phone. Measurements were taken in spring 2020 with both devices running up to date versions of their respective operating systems. 4 | 5 | If you want to run the code on Android, add NDK according to directions at https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html. Then uncomment the commented lines in `build.sh` 6 | 7 | To test the code locally, simply run `./build.sh` and then `./cargo/target/release/mybin`. You will need Rust installed. 8 | 9 | The source code is set to run the standard version of our scheme that uses curve25519. To run the mergeable scheme that uses pairings, you will need to change line 45 of `/cargo/src/lib.rs` from `test_type: Tests::Group,` to `test_type: Tests::Pairing,`. 10 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /android/.idea/.name: -------------------------------------------------------------------------------- 1 | Punch Card -------------------------------------------------------------------------------- /android/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | ndkVersion "21.0.6113669" 7 | 8 | defaultConfig { 9 | applicationId "com.example.punchcard" 10 | minSdkVersion 26 11 | targetSdkVersion 29 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | 17 | ndk { 18 | abiFilters "arm64", "armeabi", "x86" 19 | } 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | 34 | implementation 'androidx.appcompat:appcompat:1.0.2' 35 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 39 | } 40 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /android/app/src/androidTest/java/com/example/punchcard/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.punchcard; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.example.punchcard", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/punchcard/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.punchcard; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.widget.TextView; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | static { 11 | System.loadLibrary("cargo"); 12 | } 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_main); 18 | 19 | RustPunchCard g = new RustPunchCard(); 20 | String r = g.runRustCode(); 21 | ((TextView)findViewById(R.id.outputField)).setText(r); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/punchcard/RustPunchCard.java: -------------------------------------------------------------------------------- 1 | package com.example.punchcard; 2 | 3 | public class RustPunchCard { 4 | private static native String benchmarkCode(); 5 | 6 | public String runRustCode() { 7 | return benchmarkCode(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/arm64/libcargo.so: -------------------------------------------------------------------------------- 1 | /home/saba/Code/PunchCard/cargo/target/aarch64-linux-android/release/libcargo.so -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/armeabi/libcargo.so: -------------------------------------------------------------------------------- 1 | /home/saba/Code/PunchCard/cargo/target/armv7-linux-androideabi/release/libcargo.so -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/x86/libcargo.so: -------------------------------------------------------------------------------- 1 | /home/saba/Code/PunchCard/cargo/target/i686-linux-android/release/libcargo.so -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Punch Card 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /android/app/src/test/java/com/example/punchcard/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.punchcard; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.6.1' 12 | 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | 21 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SabaEskandarian/PunchCard/0dbad68cb66c6ec3f2b14930c51e98f4b957084b/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Mar 18 11:44:12 PDT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='Punch Card' 2 | include ':app' 3 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | cd cargo 2 | cargo build --release 3 | #cargo build --target aarch64-linux-android --release 4 | #cargo build --target armv7-linux-androideabi --release 5 | #cargo build --target i686-linux-android --release 6 | -------------------------------------------------------------------------------- /cargo-config.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-linux-android] 2 | ar = "/home/saba/Code/PunchCard/NDK/arm64/bin/aarch64-linux-android-ar" 3 | linker = "/home/saba/Code/PunchCard/NDK/arm64/bin/aarch64-linux-android-clang" 4 | 5 | [target.armv7-linux-androideabi] 6 | ar = "/home/saba/Code/PunchCard/NDK/arm/bin/arm-linux-androideabi-ar" 7 | linker = "/home/saba/Code/PunchCard/NDK/arm/bin/arm-linux-androideabi-clang" 8 | 9 | [target.i686-linux-android] 10 | ar = "/home/saba/Code/PunchCard/NDK/x86/bin/i686-linux-android-ar" 11 | linker = "/home/saba/Code/PunchCard/NDK/x86/bin/i686-linux-android-clang" 12 | 13 | -------------------------------------------------------------------------------- /cargo/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /cargo/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ascii" 5 | version = "0.7.1" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" 8 | 9 | [[package]] 10 | name = "autocfg" 11 | version = "1.0.0" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 14 | 15 | [[package]] 16 | name = "block-buffer" 17 | version = "0.7.3" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 20 | dependencies = [ 21 | "block-padding", 22 | "byte-tools", 23 | "byteorder", 24 | "generic-array", 25 | ] 26 | 27 | [[package]] 28 | name = "block-padding" 29 | version = "0.1.5" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 32 | dependencies = [ 33 | "byte-tools", 34 | ] 35 | 36 | [[package]] 37 | name = "byte-tools" 38 | version = "0.3.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 41 | 42 | [[package]] 43 | name = "byteorder" 44 | version = "1.3.4" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 47 | 48 | [[package]] 49 | name = "cargo" 50 | version = "0.1.0" 51 | dependencies = [ 52 | "curve25519-dalek", 53 | "ff-zeroize", 54 | "jni", 55 | "pairing-plus", 56 | "rand 0.7.3", 57 | "rand_core 0.5.1", 58 | "sha2", 59 | ] 60 | 61 | [[package]] 62 | name = "cesu8" 63 | version = "1.1.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 66 | 67 | [[package]] 68 | name = "cfg-if" 69 | version = "0.1.10" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 72 | 73 | [[package]] 74 | name = "combine" 75 | version = "2.5.2" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "1645a65a99c7c8d345761f4b75a6ffe5be3b3b27a93ee731fccc5050ba6be97c" 78 | dependencies = [ 79 | "ascii", 80 | "byteorder", 81 | ] 82 | 83 | [[package]] 84 | name = "curve25519-dalek" 85 | version = "2.0.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" 88 | dependencies = [ 89 | "byteorder", 90 | "digest", 91 | "rand_core 0.5.1", 92 | "subtle", 93 | "zeroize", 94 | ] 95 | 96 | [[package]] 97 | name = "digest" 98 | version = "0.8.1" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 101 | dependencies = [ 102 | "generic-array", 103 | ] 104 | 105 | [[package]] 106 | name = "error-chain" 107 | version = "0.10.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" 110 | 111 | [[package]] 112 | name = "fake-simd" 113 | version = "0.1.2" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 116 | 117 | [[package]] 118 | name = "ff-zeroize" 119 | version = "0.6.3" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "c02169a2e8515aa316ce516eaaf6318a76617839fbf904073284bc2576b029ee" 122 | dependencies = [ 123 | "byteorder", 124 | "ff_derive-zeroize", 125 | "rand_core 0.5.1", 126 | "zeroize", 127 | ] 128 | 129 | [[package]] 130 | name = "ff_derive-zeroize" 131 | version = "0.6.2" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "b24d4059bc0d0a0bf26b740aa21af1f96a984f0ab7a21356d00b32475388b53a" 134 | dependencies = [ 135 | "num-bigint", 136 | "num-integer", 137 | "num-traits", 138 | "proc-macro2", 139 | "quote", 140 | "syn", 141 | ] 142 | 143 | [[package]] 144 | name = "fuchsia-cprng" 145 | version = "0.1.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 148 | 149 | [[package]] 150 | name = "generic-array" 151 | version = "0.12.3" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" 154 | dependencies = [ 155 | "typenum", 156 | ] 157 | 158 | [[package]] 159 | name = "getrandom" 160 | version = "0.1.14" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" 163 | dependencies = [ 164 | "cfg-if", 165 | "libc", 166 | "wasi", 167 | ] 168 | 169 | [[package]] 170 | name = "jni" 171 | version = "0.5.3" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "cffc930ce6a38a4013e30567b559bdc79f601013ba4a81e65dbda9207263efd4" 174 | dependencies = [ 175 | "cesu8", 176 | "combine", 177 | "error-chain", 178 | "jni-sys", 179 | "log 0.3.9", 180 | ] 181 | 182 | [[package]] 183 | name = "jni-sys" 184 | version = "0.2.5" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "de0aaaba8809ab8d83a53fe2b313b996b79e8632b855eae9f70ad4323dca91b8" 187 | 188 | [[package]] 189 | name = "libc" 190 | version = "0.2.68" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" 193 | 194 | [[package]] 195 | name = "log" 196 | version = "0.3.9" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" 199 | dependencies = [ 200 | "log 0.4.8", 201 | ] 202 | 203 | [[package]] 204 | name = "log" 205 | version = "0.4.8" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 208 | dependencies = [ 209 | "cfg-if", 210 | ] 211 | 212 | [[package]] 213 | name = "num-bigint" 214 | version = "0.2.6" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" 217 | dependencies = [ 218 | "autocfg", 219 | "num-integer", 220 | "num-traits", 221 | ] 222 | 223 | [[package]] 224 | name = "num-integer" 225 | version = "0.1.42" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" 228 | dependencies = [ 229 | "autocfg", 230 | "num-traits", 231 | ] 232 | 233 | [[package]] 234 | name = "num-traits" 235 | version = "0.2.11" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" 238 | dependencies = [ 239 | "autocfg", 240 | ] 241 | 242 | [[package]] 243 | name = "opaque-debug" 244 | version = "0.2.3" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 247 | 248 | [[package]] 249 | name = "pairing-plus" 250 | version = "0.18.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "e819a65319e20573a060d027524e937f6b9c318b33215a6f0aa77726813e35c1" 253 | dependencies = [ 254 | "byteorder", 255 | "digest", 256 | "ff-zeroize", 257 | "rand 0.4.6", 258 | "rand_core 0.5.1", 259 | "rand_xorshift", 260 | "zeroize", 261 | ] 262 | 263 | [[package]] 264 | name = "ppv-lite86" 265 | version = "0.2.6" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" 268 | 269 | [[package]] 270 | name = "proc-macro2" 271 | version = "1.0.9" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" 274 | dependencies = [ 275 | "unicode-xid", 276 | ] 277 | 278 | [[package]] 279 | name = "quote" 280 | version = "1.0.3" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" 283 | dependencies = [ 284 | "proc-macro2", 285 | ] 286 | 287 | [[package]] 288 | name = "rand" 289 | version = "0.4.6" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" 292 | dependencies = [ 293 | "fuchsia-cprng", 294 | "libc", 295 | "rand_core 0.3.1", 296 | "rdrand", 297 | "winapi", 298 | ] 299 | 300 | [[package]] 301 | name = "rand" 302 | version = "0.7.3" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 305 | dependencies = [ 306 | "getrandom", 307 | "libc", 308 | "rand_chacha", 309 | "rand_core 0.5.1", 310 | "rand_hc", 311 | ] 312 | 313 | [[package]] 314 | name = "rand_chacha" 315 | version = "0.2.2" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 318 | dependencies = [ 319 | "ppv-lite86", 320 | "rand_core 0.5.1", 321 | ] 322 | 323 | [[package]] 324 | name = "rand_core" 325 | version = "0.3.1" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 328 | dependencies = [ 329 | "rand_core 0.4.2", 330 | ] 331 | 332 | [[package]] 333 | name = "rand_core" 334 | version = "0.4.2" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 337 | 338 | [[package]] 339 | name = "rand_core" 340 | version = "0.5.1" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 343 | dependencies = [ 344 | "getrandom", 345 | ] 346 | 347 | [[package]] 348 | name = "rand_hc" 349 | version = "0.2.0" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 352 | dependencies = [ 353 | "rand_core 0.5.1", 354 | ] 355 | 356 | [[package]] 357 | name = "rand_xorshift" 358 | version = "0.2.0" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" 361 | dependencies = [ 362 | "rand_core 0.5.1", 363 | ] 364 | 365 | [[package]] 366 | name = "rdrand" 367 | version = "0.4.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 370 | dependencies = [ 371 | "rand_core 0.3.1", 372 | ] 373 | 374 | [[package]] 375 | name = "sha2" 376 | version = "0.8.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" 379 | dependencies = [ 380 | "block-buffer", 381 | "digest", 382 | "fake-simd", 383 | "opaque-debug", 384 | ] 385 | 386 | [[package]] 387 | name = "subtle" 388 | version = "2.2.2" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" 391 | 392 | [[package]] 393 | name = "syn" 394 | version = "1.0.17" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" 397 | dependencies = [ 398 | "proc-macro2", 399 | "quote", 400 | "unicode-xid", 401 | ] 402 | 403 | [[package]] 404 | name = "synstructure" 405 | version = "0.12.3" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" 408 | dependencies = [ 409 | "proc-macro2", 410 | "quote", 411 | "syn", 412 | "unicode-xid", 413 | ] 414 | 415 | [[package]] 416 | name = "typenum" 417 | version = "1.11.2" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" 420 | 421 | [[package]] 422 | name = "unicode-xid" 423 | version = "0.2.0" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 426 | 427 | [[package]] 428 | name = "wasi" 429 | version = "0.9.0+wasi-snapshot-preview1" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 432 | 433 | [[package]] 434 | name = "winapi" 435 | version = "0.3.8" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 438 | dependencies = [ 439 | "winapi-i686-pc-windows-gnu", 440 | "winapi-x86_64-pc-windows-gnu", 441 | ] 442 | 443 | [[package]] 444 | name = "winapi-i686-pc-windows-gnu" 445 | version = "0.4.0" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 448 | 449 | [[package]] 450 | name = "winapi-x86_64-pc-windows-gnu" 451 | version = "0.4.0" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 454 | 455 | [[package]] 456 | name = "zeroize" 457 | version = "1.1.0" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" 460 | dependencies = [ 461 | "zeroize_derive", 462 | ] 463 | 464 | [[package]] 465 | name = "zeroize_derive" 466 | version = "1.0.0" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" 469 | dependencies = [ 470 | "proc-macro2", 471 | "quote", 472 | "syn", 473 | "synstructure", 474 | ] 475 | -------------------------------------------------------------------------------- /cargo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo" 3 | version = "0.1.0" 4 | authors = ["SabaEskandarian "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | 10 | [target.'cfg(target_os="android")'.dependencies] 11 | jni = { version = "0.5", default-features = false } 12 | 13 | [lib] 14 | crate-type = ["dylib"] 15 | path = "src/lib.rs" 16 | 17 | [[bin]] 18 | name = "mybin" 19 | path = "src/bin.rs" 20 | 21 | [dependencies] 22 | curve25519-dalek = "2" 23 | sha2 = "0.8" 24 | rand_core = "0.5.0" 25 | rand = "0.7" 26 | pairing-plus = "0.18.0" 27 | ff-zeroize="0.6.3" 28 | -------------------------------------------------------------------------------- /cargo/src/bin.rs: -------------------------------------------------------------------------------- 1 | mod lib; 2 | 3 | use std::ffi::{CString}; 4 | 5 | fn main(){ 6 | let world = lib::benchmarkCode(); 7 | let world_ptr = unsafe { CString::from_raw(world) }; 8 | let rust_string = world_ptr.to_str().unwrap(); 9 | println!("{}", rust_string); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /cargo/src/crypto.rs: -------------------------------------------------------------------------------- 1 | use sha2::Sha512; 2 | use rand_core::{RngCore, OsRng}; 3 | use curve25519_dalek::constants; 4 | use curve25519_dalek::ristretto::CompressedRistretto; 5 | use curve25519_dalek::ristretto::RistrettoPoint; 6 | use curve25519_dalek::scalar::Scalar; 7 | use std::collections::HashSet; 8 | 9 | #[derive(Debug)] 10 | pub struct ServerData { 11 | secret: Scalar, 12 | used_cards: HashSet<[u8; 32]>, 13 | pub_secret: CompressedRistretto, 14 | } 15 | 16 | #[derive(Debug)] 17 | pub struct PunchCard { 18 | card_secret: [u8; 32], 19 | punch_card: RistrettoPoint, 20 | last_mask: Scalar, 21 | count: u32, 22 | } 23 | 24 | //notation from Figure 19.7 in Boneh-Shoup textbook v0.5 25 | #[derive(Debug)] 26 | pub struct Proof { 27 | v_t: CompressedRistretto, 28 | w_t: CompressedRistretto, 29 | beta_z: [u8; 32], 30 | } 31 | 32 | fn scalar_exponentiate(base: Scalar, exp: u32) -> Scalar{ 33 | if exp == 1 { 34 | base 35 | } else if exp % 2 == 1{ 36 | base * scalar_exponentiate(base, exp - 1) 37 | } else { 38 | let val = scalar_exponentiate(base, exp/2); 39 | val * val 40 | } 41 | } 42 | 43 | 44 | impl ServerData { 45 | 46 | //set up the server secret and redeemed card db 47 | pub fn server_setup() -> (CompressedRistretto, ServerData) { 48 | 49 | let secret = Scalar::random(&mut OsRng); 50 | let used_cards = HashSet::new(); 51 | let pub_secret = &secret * &constants::RISTRETTO_BASEPOINT_TABLE; 52 | let pub_secret = pub_secret.compress(); 53 | let new_server = ServerData { 54 | secret, 55 | used_cards, 56 | pub_secret, 57 | }; 58 | 59 | (pub_secret, new_server) 60 | } 61 | 62 | //punch card by multiplying by secret 63 | //prove that this was done honestly 64 | pub fn server_punch(&self, card: CompressedRistretto) -> (CompressedRistretto, Proof) { 65 | 66 | let card_dec = card.decompress().expect("couldn't decompress point in server_punch"); 67 | let new_card_dec = card_dec * self.secret; 68 | let new_card = new_card_dec.compress(); 69 | 70 | //generate Chaum-Pedersen proof 71 | //see Boneh Shoup textbook v0.5 Figure 19.7 72 | let beta_t = Scalar::random(&mut OsRng); 73 | let v_t = &beta_t * &constants::RISTRETTO_BASEPOINT_TABLE; 74 | let v_t_compress = v_t.compress(); 75 | let w_t = card_dec * beta_t; 76 | let w_t_compress = w_t.compress(); 77 | 78 | let mut hashinput: Vec = Vec::new(); 79 | hashinput.extend_from_slice(&self.pub_secret.to_bytes()); 80 | hashinput.extend_from_slice(&card.to_bytes()); 81 | hashinput.extend_from_slice(&new_card.to_bytes()); 82 | hashinput.extend_from_slice(&v_t_compress.to_bytes()); 83 | hashinput.extend_from_slice(&w_t_compress.to_bytes()); 84 | let hashinput_bytes: &[u8] = &hashinput; 85 | let chal = Scalar::hash_from_bytes::(hashinput_bytes); 86 | let beta_z = beta_t + self.secret * chal; 87 | 88 | let proof = Proof { 89 | v_t: v_t_compress, 90 | w_t: w_t_compress, 91 | beta_z: beta_z.to_bytes(), 92 | }; 93 | 94 | (new_card, proof) 95 | } 96 | 97 | //check that the punch card is valid with num_punches 98 | //check that the punch card secret is new 99 | pub fn server_verify(&mut self, card: CompressedRistretto, card_secret: [u8; 32], num_punches: u32) -> bool { 100 | 101 | let num_punches = scalar_exponentiate(self.secret, num_punches); 102 | let expected_card = RistrettoPoint::hash_from_bytes::(&card_secret) * num_punches; 103 | 104 | 105 | if card == expected_card.compress() { 106 | //returns true if this was not in the set 107 | self.used_cards.insert(card_secret) 108 | } else { 109 | false 110 | } 111 | } 112 | 113 | pub fn count_cards(&self) -> usize { 114 | self.used_cards.len() 115 | } 116 | 117 | //preload the database of used cards with num entries 118 | pub fn cheat_setup_db(&mut self, num:u32) { 119 | for i in 0..num { 120 | let temp = Scalar::from(i).to_bytes(); 121 | self.used_cards.insert(temp); 122 | } 123 | } 124 | 125 | pub fn lookup_test(&self, input: [u8; 32]) -> bool { 126 | self.used_cards.contains(&input) 127 | } 128 | } 129 | 130 | 131 | impl PunchCard { 132 | 133 | //create a new punchcard 134 | //punch card is already masked after this function 135 | pub fn card_setup() -> (CompressedRistretto, PunchCard) { 136 | 137 | let mut card_secret = [0u8; 32]; 138 | OsRng.fill_bytes(&mut card_secret); 139 | 140 | let last_mask = Scalar::random(&mut OsRng); 141 | 142 | //the punch card is already masked at this point 143 | let punch_card = RistrettoPoint::hash_from_bytes::(&card_secret) * last_mask; 144 | 145 | let new_punch_card = PunchCard { 146 | card_secret, 147 | punch_card, 148 | last_mask, 149 | count: 0, 150 | }; 151 | 152 | (new_punch_card.punch_card.compress(), new_punch_card) 153 | } 154 | 155 | //verify proof from the server 156 | //if accepted, unmask punchcard, remask with new mask, increment count 157 | //otherwise reuse old punchcard, same count 158 | pub fn verify_remask(&mut self, card: CompressedRistretto, pub_secret: CompressedRistretto, 159 | proof: Proof) -> (CompressedRistretto, bool) { 160 | 161 | //verify Chaum-Pedersen proof 162 | //see Boneh Shoup textbook v0.5 Figure 19.7 163 | let mut hashinput: Vec = Vec::new(); 164 | hashinput.extend_from_slice(&pub_secret.to_bytes()); 165 | hashinput.extend_from_slice(&self.punch_card.compress().to_bytes()); 166 | hashinput.extend_from_slice(&card.to_bytes()); 167 | hashinput.extend_from_slice(&proof.v_t.to_bytes()); 168 | hashinput.extend_from_slice(&proof.w_t.to_bytes()); 169 | let hashinput_bytes: &[u8] = &hashinput; 170 | let chal = Scalar::hash_from_bytes::(hashinput_bytes); 171 | 172 | let gbz: RistrettoPoint = &Scalar::from_bytes_mod_order(proof.beta_z) * &constants::RISTRETTO_BASEPOINT_TABLE; 173 | let vtvc = proof.v_t.decompress().expect("couldn't decompress in verify_remask") 174 | + (pub_secret.decompress().expect("couldn't decompress pub_secret in verify_remask") 175 | * chal); 176 | let ubz = self.punch_card * Scalar::from_bytes_mod_order(proof.beta_z); 177 | let wtwc = proof.w_t.decompress().expect("couldn't decompress in verify_remask") 178 | + (card.decompress().expect("couldn't decompress in verify_remask") * chal); 179 | 180 | 181 | let mut success = true; 182 | if gbz == vtvc && ubz == wtwc { 183 | //if true { //for debugging 184 | let unmasked_card = card.decompress() 185 | .expect("couldn't decompress point in verify_remask") 186 | * self.last_mask.invert(); 187 | self.last_mask = Scalar::random(&mut OsRng); 188 | self.punch_card = unmasked_card * self.last_mask; 189 | self.count += 1; 190 | } else { 191 | success = false; 192 | } 193 | 194 | (self.punch_card.compress(), success) 195 | } 196 | 197 | //unmask the punch card and return its relevant contents 198 | pub fn unmask_redeem(&mut self) -> ([u8; 32], CompressedRistretto) { 199 | 200 | self.punch_card = self.punch_card * self.last_mask.invert(); 201 | 202 | (self.card_secret, self.punch_card.compress()) 203 | } 204 | 205 | pub fn get_count(&self) -> u32 { 206 | self.count 207 | } 208 | 209 | pub fn exp_test(&self) -> RistrettoPoint{ 210 | self.punch_card * self.last_mask 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /cargo/src/crypto_pairing.rs: -------------------------------------------------------------------------------- 1 | //use sha2::Sha512; 2 | use sha2::Sha256; 3 | use rand_core::{RngCore, OsRng}; 4 | use std::collections::HashSet; 5 | use curve25519_dalek::scalar::Scalar; 6 | use ff_zeroize::Field; 7 | use ff_zeroize::PrimeField; 8 | use pairing_plus::Engine; 9 | use pairing_plus::hash_to_field::ExpandMsgXmd; 10 | use pairing_plus::CurveProjective; 11 | use pairing_plus::serdes::SerDes; 12 | use pairing_plus::hash_to_field::hash_to_field; 13 | use pairing_plus::hash_to_curve::HashToCurve; 14 | use pairing_plus::bls12_381::Bls12; 15 | use pairing_plus::bls12_381::Fr; 16 | use pairing_plus::bls12_381::G1; 17 | use pairing_plus::bls12_381::G2; 18 | use pairing_plus::bls12_381::Fq12; 19 | 20 | 21 | //Making a second module with all the same functions used in crypto.rs 22 | //but for the version that uses pairings to merge 2 cards 23 | //Not the right way to do this, but it will do for now 24 | 25 | #[derive(Debug)] 26 | pub struct PairServerData { 27 | secret: Fr, 28 | used_cards: HashSet<[u8; 32]>, 29 | pub pub_secret_g1: Vec, //compressed form of g1^secret 30 | pub pub_secret_g2: Vec, //compressed form of g2^secret 31 | } 32 | 33 | //this holds the two parts of one punch card 34 | #[derive(Debug)] 35 | pub struct PairPunchCard { 36 | g1card: PairPunchCardPart, 37 | g2card: PairPunchCardPart, 38 | } 39 | 40 | //This is one punch card part 41 | #[derive(Debug)] 42 | pub struct PairPunchCardPart { 43 | card_secret: [u8; 32], 44 | punch_card: T, 45 | last_mask: Fr, 46 | count: u32, 47 | } 48 | 49 | //we'll use two proofs, one for the exponentiation in each group 50 | //notation from Figure 19.7 in Boneh-Shoup textbook v0.5 51 | #[derive(Debug)] 52 | pub struct PairProof { 53 | v_t: Vec,//compressed points in G1 or G2 (depending on proof) 54 | w_t: Vec, 55 | beta_z: Vec,//compressed point in Fr 56 | } 57 | 58 | impl PairServerData { 59 | 60 | //set up the server secret and redeemed card 61 | pub fn pair_server_setup() -> PairServerData{ 62 | let secret = Fr::random(&mut OsRng); 63 | let used_cards = HashSet::new(); 64 | let mut pub_secret_g1 = Vec::::new(); 65 | let mut pub_secret_g2 = Vec::::new(); 66 | let mut temp = G1::one(); 67 | temp.mul_assign(secret); 68 | temp.serialize(&mut pub_secret_g1, true).expect("couldn't serialize"); 69 | let mut temp = G2::one(); 70 | temp.mul_assign(secret); 71 | temp.serialize(&mut pub_secret_g2, true).expect("couldn't serialize"); 72 | let new_server = PairServerData { 73 | secret, 74 | used_cards, 75 | pub_secret_g1, 76 | pub_secret_g2, 77 | }; 78 | new_server 79 | } 80 | 81 | pub fn pair_server_punch(&self, compressed_card1: &mut Vec, compressed_card2: &mut Vec) -> (Vec, Vec, PairProof, PairProof) { 82 | let dst1 = [3u8, 0u8, 0u8, 0u8]; 83 | let dst2 = [4u8, 0u8, 0u8, 0u8]; 84 | 85 | let (card1, proof1) = self.pair_server_punch_part::(compressed_card1, dst1); 86 | let (card2, proof2) = self.pair_server_punch_part::(compressed_card2, dst2); 87 | 88 | (card1, card2, proof1, proof2) 89 | } 90 | 91 | //this will have to be called twice, once for each piece of the card 92 | //dst is also 3,0,0,0 the first time and 4,0,0,0 the second time 93 | //punch card by multiplying by secret 94 | //prove that this was done honestly 95 | fn pair_server_punch_part(&self, compressed_card: &mut Vec, dst: [u8; 4]) -> (Vec, PairProof) 96 | where T: CurveProjective + SerDes, 97 | <::Scalar as ff_zeroize::PrimeField>::Repr: std::convert::From 98 | { 99 | 100 | let pub_secret: &[u8]; 101 | if dst[0] == 3 { 102 | pub_secret = &self.pub_secret_g1; 103 | } else if dst[0] == 4 { 104 | pub_secret = &self.pub_secret_g2; 105 | } else { 106 | panic!("bad dst"); 107 | } 108 | 109 | //deserialize the card given as parameter 110 | let card = T::deserialize(&mut &compressed_card[..], true).expect("couldn't deserialize"); 111 | let mut new_card = card.clone(); 112 | new_card.mul_assign(self.secret); 113 | let mut new_compressed_card = Vec::::new(); 114 | new_card.serialize(&mut new_compressed_card, true).expect("couldn't serialize"); 115 | 116 | //generate Chaum-Pedersen proof 117 | //see Boneh Shoup textbook v0.5 Figure 19.7 118 | let beta_t = Fr::random(&mut OsRng); 119 | let mut v_t = T::one(); 120 | v_t.mul_assign(beta_t); 121 | let mut v_t_compressed = Vec::::new(); 122 | v_t.serialize(&mut v_t_compressed, true).expect("couldn't serialize"); 123 | 124 | let mut w_t = card.clone(); 125 | w_t.mul_assign(beta_t); 126 | let mut w_t_compressed = Vec::::new(); 127 | w_t.serialize(&mut w_t_compressed, true).expect("couldn't serialize"); 128 | 129 | let mut hashinput: Vec = Vec::new(); 130 | hashinput.extend_from_slice(pub_secret); 131 | hashinput.extend_from_slice(&compressed_card); 132 | hashinput.extend_from_slice(&new_compressed_card); 133 | hashinput.extend_from_slice(&v_t_compressed); 134 | hashinput.extend_from_slice(&w_t_compressed); 135 | let hashinput_bytes: &[u8] = &hashinput; 136 | 137 | let chal = hash_to_field::>(hashinput_bytes, &dst, 1)[0]; 138 | 139 | let mut beta_z = chal; 140 | beta_z.mul_assign(&self.secret); 141 | beta_z.add_assign(&beta_t); 142 | 143 | let mut beta_z_compressed = Vec::::new(); 144 | beta_z.serialize(&mut beta_z_compressed, true).expect("couldn't serialize"); 145 | 146 | //println!("size of Fr compressed: {}", beta_z_compressed.len());//it's 32 147 | let proof = PairProof { 148 | v_t: v_t_compressed, 149 | w_t: w_t_compressed, 150 | beta_z: beta_z_compressed, 151 | }; 152 | 153 | (new_compressed_card, proof) 154 | 155 | } 156 | 157 | 158 | //check that the punch card is valid with num_punches 159 | //check that the punch card secret is new 160 | pub fn pair_server_verify(&mut self, compressed_card1: &mut Vec, secret1: [u8; 32], secret2: [u8; 32], num_punches: u32) -> bool { 161 | 162 | let csuite1 = [0u8; 4]; 163 | let csuite2 = [1u8, 0u8, 0u8, 0u8]; 164 | 165 | //compute the values and pairings you would expect 166 | let num_punches = self.secret.pow([num_punches as u64]); 167 | let mut expcard_1_1 = >>::hash_to_curve(&secret1, &csuite1); 168 | //let expcard_1_2 = >>::hash_to_curve(&secret1, &csuite2); 169 | //let mut expcard_2_1 = >>::hash_to_curve(&secret2, &csuite1); 170 | let expcard_2_2 = >>::hash_to_curve(&secret2, &csuite2); 171 | 172 | expcard_1_1.mul_assign(num_punches); 173 | //expcard_2_1.mul_assign(num_punches); 174 | 175 | let exp_pairing_1 = Bls12::pairing(expcard_1_1, expcard_2_2); 176 | //let exp_pairing_2 = Bls12::pairing(expcard_2_1, expcard_1_2); 177 | 178 | 179 | //deserialize the cards given as parameters 180 | let card1 = Fq12::deserialize(&mut &compressed_card1[..], true).expect("couldn't deserialize"); 181 | //let card2 = Fq12::deserialize(&mut &compressed_card2[..], true).expect("couldn't deserialize"); 182 | 183 | //check that the card is valid (real and expected values match) 184 | if card1 == exp_pairing_1 { 185 | //check that the secrets are new 186 | //returns true if this was not in the set 187 | self.used_cards.insert(secret1) && self.used_cards.insert(secret2) 188 | } else { 189 | false 190 | } 191 | } 192 | 193 | //preload the database of used cards with num entries 194 | pub fn pair_cheat_setup_db(&mut self, num:u32) { 195 | for i in 0..num { 196 | //this is weird, but it's a hack anyway 197 | let temp = Scalar::from(i).to_bytes(); 198 | self.used_cards.insert(temp); 199 | } 200 | } 201 | 202 | pub fn pair_count_cards(&self) -> usize { 203 | self.used_cards.len() 204 | } 205 | 206 | } 207 | 208 | impl PairPunchCard { 209 | 210 | //new mergable punchcard 211 | pub fn card_setup() -> (Vec, Vec, PairPunchCard) { 212 | 213 | //giving the same secret to both cards 214 | //different domain separators 215 | let mut card_secret = [0u8; 32]; 216 | OsRng.fill_bytes(&mut card_secret); 217 | let csuite1 = [0u8; 4]; 218 | let csuite2 = [1u8, 0u8, 0u8, 0u8]; 219 | 220 | let (card1, client1) = Self::card_part_setup::(card_secret, csuite1); 221 | let (card2, client2) = Self::card_part_setup::(card_secret, csuite2); 222 | 223 | let new_card = PairPunchCard { 224 | g1card: client1, 225 | g2card: client2, 226 | }; 227 | 228 | (card1, card2, new_card) 229 | 230 | } 231 | 232 | //create a new punchcard part 233 | //punch card is already masked after this function 234 | fn card_part_setup(card_secret: [u8; 32], csuite: [u8; 4]) -> (Vec, PairPunchCardPart::) 235 | where T: CurveProjective + SerDes + HashToCurve>, 236 | <::Scalar as PrimeField>::Repr: std::convert::From 237 | { 238 | 239 | let last_mask = Fr::random(&mut OsRng); 240 | 241 | let mut punch_card = >>::hash_to_curve(&card_secret, &csuite); 242 | punch_card.mul_assign(last_mask); 243 | 244 | let new_punch_card = PairPunchCardPart:: { 245 | card_secret, 246 | punch_card, 247 | last_mask, 248 | count: 0, 249 | }; 250 | 251 | let mut card_compressed = Vec::::new(); 252 | new_punch_card.punch_card.serialize(&mut card_compressed, true).expect("couldn't serialize"); 253 | 254 | (card_compressed, new_punch_card) 255 | 256 | } 257 | 258 | pub fn verify_remask(&mut self, compressed_card1: Vec, compressed_card2: Vec, pub_secret_g1: &Vec, pub_secret_g2: &Vec, proof1: PairProof, proof2: PairProof) -> (Vec, Vec, bool) { 259 | 260 | let dst1 = [3u8, 0u8, 0u8, 0u8]; 261 | let dst2 = [4u8, 0u8, 0u8, 0u8]; 262 | 263 | let (card1, success1) = Self::verify_remask_part::(&mut self.g1card, compressed_card1, pub_secret_g1, proof1, dst1); 264 | let (card2, success2) = Self::verify_remask_part::(&mut self.g2card, compressed_card2, pub_secret_g2, proof2, dst2); 265 | 266 | if success1 != success2 {panic!("success values don't match");} 267 | 268 | (card1, card2, success1) 269 | } 270 | 271 | //verify proof from the server 272 | //if accepted, unmask punchcard, remask with new mask, increment count 273 | //otherwise reuse old punchcard, same count 274 | fn verify_remask_part(card: &mut PairPunchCardPart, new_compressed_card: Vec, pub_secret: &Vec, proof: PairProof, dst: [u8; 4]) -> (Vec, bool) 275 | where T: CurveProjective + SerDes, 276 | <::Scalar as ff_zeroize::PrimeField>::Repr: std::convert::From 277 | { 278 | 279 | //serialize the punch card so it can be used here 280 | let mut compressed_card = Vec::::new(); 281 | card.punch_card.serialize(&mut compressed_card, true).expect("couldn't serialize"); 282 | 283 | //verify Chaum-Pedersen proof 284 | //see Boneh Shoup textbook v0.5 Figure 19.7 285 | let mut hashinput: Vec = Vec::new(); 286 | hashinput.extend_from_slice(pub_secret); 287 | hashinput.extend_from_slice(&compressed_card); 288 | hashinput.extend_from_slice(&new_compressed_card); 289 | hashinput.extend_from_slice(&proof.v_t); 290 | hashinput.extend_from_slice(&proof.w_t); 291 | let hashinput_bytes: &[u8] = &hashinput; 292 | let chal = hash_to_field::>(hashinput_bytes, &dst, 1)[0]; 293 | 294 | //decompress proof elements and remaining inputs 295 | let pub_secret = T::deserialize(&mut &pub_secret[..], true).expect("couldn't deserialize"); 296 | let v_t = T::deserialize(&mut &proof.v_t[..], true).expect("couldn't deserialize"); 297 | let w_t = T::deserialize(&mut &proof.w_t[..], true).expect("couldn't deserialize"); 298 | let mut new_card = T::deserialize(&mut &new_compressed_card[..], true).expect("couldn't deserialize"); 299 | let beta_z = Fr::deserialize(&mut &proof.beta_z[..], true).expect("couldn't deserialize"); 300 | 301 | let mut gbz = T::one(); 302 | gbz.mul_assign(beta_z); 303 | 304 | let mut vtvc = v_t; 305 | let mut part = pub_secret; 306 | part.mul_assign(chal); 307 | vtvc.add_assign(&part); 308 | 309 | let mut ubz = card.punch_card; 310 | ubz.mul_assign(beta_z); 311 | 312 | let mut wtwc = w_t; 313 | let mut part = new_card; 314 | part.mul_assign(chal); 315 | wtwc.add_assign(&part); 316 | 317 | let mut success = true; 318 | if gbz == vtvc && ubz == wtwc { 319 | new_card.mul_assign(card.last_mask.inverse().expect("couldn't invert!")); 320 | card.last_mask = Fr::random(&mut OsRng); 321 | new_card.mul_assign(card.last_mask); 322 | card.punch_card = new_card; 323 | card.count += 1; 324 | } else { 325 | success = false; 326 | } 327 | 328 | //serialize new card 329 | let mut new_card_compressed = Vec::::new(); 330 | new_card.serialize(&mut new_card_compressed, true).expect("couldn't serialize"); 331 | 332 | (new_card_compressed, success) 333 | } 334 | 335 | //unmask the punch card, use pairings to merge, and return relevant contents 336 | pub fn pair_unmask_redeem(&mut self, mut other: PairPunchCard) -> ([u8; 32], [u8; 32], Vec) { 337 | 338 | //unmask the punch cards 339 | self.g1card.punch_card.mul_assign(self.g1card.last_mask.inverse().expect("couldn't invert!")); 340 | //self.g2card.punch_card.mul_assign(self.g2card.last_mask.inverse().expect("couldn't invert!")); 341 | //other.g1card.punch_card.mul_assign(other.g1card.last_mask.inverse().expect("couldn't invert!")); 342 | other.g2card.punch_card.mul_assign(other.g2card.last_mask.inverse().expect("couldn't invert!")); 343 | 344 | //pairings of the parts of the punch cards 345 | let pairing1 = Bls12::pairing(self.g1card.punch_card, other.g2card.punch_card); 346 | //let pairing2 = Bls12::pairing(other.g1card.punch_card, self.g2card.punch_card); 347 | 348 | //serialize pairing outputs 349 | let mut pairing1_compressed = Vec::::new(); 350 | //let mut pairing2_compressed = Vec::::new(); 351 | pairing1.serialize(&mut pairing1_compressed, true).expect("couldn't serialize"); 352 | //pairing2.serialize(&mut pairing2_compressed, true).expect("couldn't serialize"); 353 | 354 | 355 | //return the secrets from the punch cards and the results of the pairings 356 | //since both parts of each card use the same secret, we only need one from each 357 | (self.g1card.card_secret, other.g1card.card_secret, pairing1_compressed)//, pairing2_compressed) 358 | } 359 | 360 | pub fn pair_get_count(&self) -> u32 { 361 | if self.g1card.count != self.g2card.count {panic!("card counts misaligned!")} 362 | 363 | self.g1card.count 364 | } 365 | 366 | pub fn exp_test_g1(&mut self) -> G1{ 367 | self.g1card.punch_card.mul_assign(self.g1card.last_mask); 368 | self.g1card.punch_card 369 | } 370 | 371 | pub fn exp_test_g2(&mut self) -> G2{ 372 | self.g2card.punch_card.mul_assign(self.g2card.last_mask); 373 | self.g2card.punch_card 374 | } 375 | 376 | pub fn pair_test(&mut self) -> Fq12{ 377 | Bls12::pairing(self.g1card.punch_card, self.g2card.punch_card) 378 | } 379 | 380 | } 381 | -------------------------------------------------------------------------------- /cargo/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod crypto; 2 | mod crypto_pairing; 3 | 4 | use std::os::raw::{c_char}; 5 | use std::ffi::{CString}; 6 | use crypto::ServerData; 7 | use crypto::PunchCard; 8 | use crypto_pairing::PairServerData; 9 | use crypto_pairing::PairPunchCard; 10 | use std::time::Instant; 11 | use curve25519_dalek::scalar::Scalar; 12 | use rand::Rng; 13 | 14 | 15 | enum Tests { 16 | Group, 17 | Lookup, 18 | Pairing, 19 | } 20 | 21 | struct Times { 22 | num_iterations: u32, 23 | num_punches: u32, 24 | setup_rows: u32, 25 | test_type: Tests, 26 | server_setup: u128, 27 | client_setup: u128, 28 | server_punch: u128, 29 | client_punch: u128, 30 | client_redeem: u128, 31 | server_redeem: u128, 32 | } 33 | 34 | #[no_mangle] 35 | pub extern fn benchmarkCode() -> *mut c_char { 36 | //call and time crypto code here 37 | //write performance numbers to the string that gets returned 38 | 39 | 40 | 41 | let mut times = Times { 42 | num_iterations: 1000, //how many iterations to average over 43 | num_punches: 10, //how many punches before a card is redeemed, must be even for the pairing version test code 44 | setup_rows: 0, //change to larger number to test with used cards in db, also make this larger for the lookup test (or else it will crash) 45 | test_type: Tests::Group, 46 | server_setup: 0, 47 | client_setup: 0, 48 | server_punch: 0, 49 | client_punch: 0, 50 | client_redeem: 0, 51 | server_redeem: 0, 52 | }; 53 | 54 | let perf_string: &str; 55 | 56 | match times.test_type { 57 | Tests::Group => { 58 | for _ in 0..times.num_iterations { 59 | //if j % 10 == 0 {println!("10 more done!\n");} 60 | 61 | //set up server 62 | let now = Instant::now(); 63 | let (pub_secret, mut server) = ServerData::server_setup(); 64 | let elapsed = now.elapsed().as_micros(); 65 | //println!("time elapsed in server setup: {}", elapsed); 66 | times.server_setup += elapsed; 67 | 68 | //fill up database of used cards 69 | server.cheat_setup_db(times.setup_rows); 70 | 71 | //println!("number of used punchcards: {}", server.count_cards()); 72 | 73 | //create new punchcard 74 | let now = Instant::now(); 75 | let (mut current_card, mut client) = PunchCard::card_setup(); 76 | let elapsed = now.elapsed().as_micros(); 77 | //println!("time elapsed in punchcard setup: {}", elapsed); 78 | times.client_setup += elapsed; 79 | 80 | 81 | //punch the card 82 | for i in 0..times.num_punches { 83 | 84 | //server punches 85 | let now = Instant::now(); 86 | let (new_card, proof) = server.server_punch(current_card); 87 | let elapsed = now.elapsed().as_micros(); 88 | //println!("time elapsed in server punch: {}", elapsed); 89 | times.server_punch += elapsed; 90 | 91 | //client verifies punch, prepares for next punch 92 | let now = Instant::now(); 93 | let res = client.verify_remask(new_card, pub_secret, proof); 94 | current_card = res.0; 95 | let punch_success = res.1; 96 | let elapsed = now.elapsed().as_micros(); 97 | if !punch_success {panic!("punch failed");} 98 | //println!("time elapsed in client punch: {}", elapsed); 99 | times.client_punch += elapsed; 100 | 101 | //println!("punch succeeded? {}", punch_success); 102 | //println!("punch count: {}", client.get_count()); 103 | if client.get_count() != i+1 {panic!("punch count wrong");} 104 | } 105 | 106 | 107 | //client redeems card 108 | let now = Instant::now(); 109 | let (card_secret, final_card) = client.unmask_redeem(); 110 | let elapsed = now.elapsed().as_micros(); 111 | //println!("time elapsed in redemption (client): {}", elapsed); 112 | times.client_redeem += elapsed; 113 | 114 | //server verifies card 115 | let now = Instant::now(); 116 | let redeem_success = server.server_verify(final_card, card_secret, times.num_punches); 117 | if !redeem_success {panic!("redemption failed");} 118 | let elapsed = now.elapsed().as_micros(); 119 | //println!("time elapsed in redemption (server): {}", elapsed); 120 | times.server_redeem += elapsed; 121 | 122 | //println!("card redemption succeeded? {}", redeem_success); 123 | //println!("number of used punchcards: {}", server.count_cards()); 124 | if server.count_cards() != (times.setup_rows + 1) as usize {panic!("wrong number of rows in card database");} 125 | 126 | } 127 | 128 | perf_string = "Performance Results for 25519 group\n"; 129 | }, 130 | Tests::Lookup => { 131 | //mostly using this as scratch space for miscellaneous experiments 132 | let (_, mut server) = ServerData::server_setup(); 133 | server.cheat_setup_db(times.setup_rows); 134 | let (_, client) = PunchCard::card_setup(); 135 | let mut rng = rand::thread_rng(); 136 | 137 | let (_, _, mut pairing_client) = PairPunchCard::card_setup(); 138 | 139 | for _ in 0..times.num_iterations { 140 | let x:u32 = rng.gen_range(0, times.setup_rows); 141 | let val = Scalar::from(x).to_bytes(); 142 | 143 | 144 | let now = Instant::now(); 145 | let there = server.lookup_test(val); 146 | let elapsed = now.elapsed().as_nanos(); 147 | //println!("time elapsed in redemption (server): {}", elapsed); 148 | times.server_setup += elapsed; 149 | if !there {panic!("wasn't there!");} 150 | 151 | 152 | let now = Instant::now(); 153 | let _res = client.exp_test(); 154 | let elapsed = now.elapsed().as_micros(); 155 | times.client_setup += elapsed; 156 | 157 | 158 | 159 | let now = Instant::now(); 160 | let _res = pairing_client.exp_test_g1(); 161 | let elapsed = now.elapsed().as_micros(); 162 | times.client_redeem += elapsed; 163 | 164 | let now = Instant::now(); 165 | let _res = pairing_client.exp_test_g2(); 166 | let elapsed = now.elapsed().as_micros(); 167 | times.server_redeem += elapsed; 168 | 169 | let now = Instant::now(); 170 | let _res = pairing_client.pair_test(); 171 | let elapsed = now.elapsed().as_micros(); 172 | times.server_punch += elapsed; 173 | } 174 | 175 | perf_string = "Performance Results for misc experiment\n"; 176 | }, 177 | Tests::Pairing => { 178 | //similar to the group code above, but for the pairing version 179 | //we will create 2 cards and punch each 5 times, then merge them to redeem 180 | for j in 0..times.num_iterations { 181 | if j % 10 == 0 {println!("10 more done!\n");} 182 | 183 | //set up server 184 | let now = Instant::now(); 185 | let mut server = PairServerData::pair_server_setup(); 186 | let elapsed = now.elapsed().as_micros(); 187 | //println!("time elapsed in server setup: {}", elapsed); 188 | times.server_setup += elapsed; 189 | 190 | //fill up database of used cards 191 | //double because each card is actually 2 cards 192 | server.pair_cheat_setup_db(2*times.setup_rows); 193 | 194 | //println!("number of used punchcards: {}", server.count_cards()); 195 | 196 | //create new punchcard 197 | let now = Instant::now(); 198 | let (mut current_card_g1, mut current_card_g2, mut client) = PairPunchCard::card_setup(); 199 | let elapsed = now.elapsed().as_micros(); 200 | //println!("time elapsed in punchcard setup: {}", elapsed); 201 | times.client_setup += elapsed; 202 | 203 | //create a second card that's going to be merged with the first 204 | let (mut second_current_card_g1, mut second_current_card_g2, mut second_client) = PairPunchCard::card_setup(); 205 | 206 | 207 | //punch the first card 208 | for i in 0..times.num_punches/2 { 209 | 210 | //server punches 211 | let now = Instant::now(); 212 | let (new_card_g1, new_card_g2, proof_g1, proof_g2) = server.pair_server_punch(&mut current_card_g1, &mut current_card_g2); 213 | let elapsed = now.elapsed().as_micros(); 214 | //println!("time elapsed in server punch: {}", elapsed); 215 | times.server_punch += elapsed; 216 | 217 | //client verifies punch, prepares for next punch 218 | let now = Instant::now(); 219 | let res = client.verify_remask(new_card_g1, new_card_g2, &server.pub_secret_g1, &server.pub_secret_g2, proof_g1, proof_g2); 220 | current_card_g1 = res.0; 221 | current_card_g2 = res.1; 222 | let punch_success = res.2; 223 | let elapsed = now.elapsed().as_micros(); 224 | if !punch_success {panic!("punch failed");} 225 | //println!("time elapsed in client punch: {}", elapsed); 226 | times.client_punch += elapsed; 227 | 228 | //println!("punch succeeded? {}", punch_success); 229 | //println!("punch count: {}", client.get_count()); 230 | if client.pair_get_count() != i+1 {panic!("first punch count wrong");} 231 | } 232 | //punch the second card 233 | for i in 0..times.num_punches/2 { 234 | 235 | //server punches 236 | let now = Instant::now(); 237 | let (new_card_g1, new_card_g2, proof_g1, proof_g2) = server.pair_server_punch(&mut second_current_card_g1, &mut second_current_card_g2); 238 | let elapsed = now.elapsed().as_micros(); 239 | //println!("time elapsed in server punch: {}", elapsed); 240 | times.server_punch += elapsed; 241 | 242 | //client verifies punch, prepares for next punch 243 | let now = Instant::now(); 244 | let res = second_client.verify_remask(new_card_g1, new_card_g2, &server.pub_secret_g1, &server.pub_secret_g2, proof_g1, proof_g2); 245 | second_current_card_g1 = res.0; 246 | second_current_card_g2 = res.1; 247 | let punch_success = res.2; 248 | let elapsed = now.elapsed().as_micros(); 249 | if !punch_success {panic!("punch failed");} 250 | //println!("time elapsed in client punch: {}", elapsed); 251 | times.client_punch += elapsed; 252 | 253 | //println!("punch succeeded? {}", punch_success); 254 | //println!("punch count: {}", client.get_count()); 255 | if second_client.pair_get_count() != i+1 {panic!("second punch count wrong");} 256 | } 257 | 258 | 259 | //client redeems card 260 | let now = Instant::now(); 261 | let (card_secret, second_card_secret, mut final_card) = client.pair_unmask_redeem(second_client); 262 | let elapsed = now.elapsed().as_micros(); 263 | //println!("time elapsed in redemption (client): {}", elapsed); 264 | times.client_redeem += elapsed; 265 | 266 | //server verifies card 267 | let now = Instant::now(); 268 | let redeem_success = server.pair_server_verify(&mut final_card, card_secret, second_card_secret, times.num_punches); 269 | if !redeem_success {panic!("redemption failed");} 270 | let elapsed = now.elapsed().as_micros(); 271 | //println!("time elapsed in redemption (server): {}", elapsed); 272 | times.server_redeem += elapsed; 273 | 274 | //println!("card redemption succeeded? {}", redeem_success); 275 | //println!("number of used punchcards: {}", server.count_cards()); 276 | if server.pair_count_cards() != (2*times.setup_rows + 2) as usize {panic!("wrong number of rows in card database");} 277 | 278 | } 279 | 280 | perf_string = "Performance Results for BLS12_381 group with merging\n"; 281 | 282 | 283 | }, 284 | } 285 | 286 | 287 | 288 | 289 | 290 | let perf_string = perf_string.to_owned() + 291 | &"Each operation is repeated for ".to_owned() 292 | + ×.num_iterations.to_string().to_owned() + 293 | &" iterations, except punches, which are done ".to_owned() 294 | + &(times.num_iterations*times.num_punches).to_string().to_owned() + 295 | &" times (".to_owned() 296 | + ×.num_punches.to_string().to_owned() + 297 | &" punches per iteration). \nThe server database starts with ".to_owned() 298 | + ×.setup_rows.to_string().to_owned() + 299 | &" used punchcards in each iteration.".to_owned() + 300 | &" \nNumbers are cumulative over all runs, in microseconds.\n".to_owned() + 301 | &"Server setup: ".to_owned() + ×.server_setup.to_string().to_owned() + 302 | &"\nClient setup: ".to_owned() + ×.client_setup.to_string().to_owned() + 303 | &"\nServer punch: ".to_owned() + ×.server_punch.to_string().to_owned() + 304 | &"\nClient punch: ".to_owned() + ×.client_punch.to_string().to_owned() + 305 | &"\nClient redeem: ".to_owned() + ×.client_redeem.to_string().to_owned() + 306 | &"\nServer redeem: ".to_owned() + ×.server_redeem.to_string().to_owned() + 307 | &"\n".to_owned(); 308 | 309 | CString::new(perf_string.to_owned()).unwrap().into_raw() 310 | } 311 | 312 | /// Expose the JNI interface for android below 313 | #[cfg(target_os="android")] 314 | #[allow(non_snake_case)] 315 | pub mod android { 316 | extern crate jni; 317 | 318 | use super::*; 319 | use self::jni::JNIEnv; 320 | use self::jni::objects::{JClass}; 321 | use self::jni::sys::{jstring}; 322 | 323 | #[no_mangle] 324 | pub unsafe extern fn Java_com_example_punchcard_RustPunchCard_benchmarkCode(env: JNIEnv, _: JClass) -> jstring { 325 | // Our Java companion code might pass-in "world" as a string, hence the name. 326 | let world = benchmarkCode(); 327 | // Retake pointer so that we can use it below and allow memory to be freed when it goes out of scope. 328 | let world_ptr = CString::from_raw(world); 329 | let output = env.new_string(world_ptr.to_str().unwrap()).expect("Couldn't create java string!"); 330 | 331 | output.into_inner() 332 | } 333 | } 334 | 335 | -------------------------------------------------------------------------------- /cargo/src/lib/crypto.rs: -------------------------------------------------------------------------------- 1 | ../crypto.rs -------------------------------------------------------------------------------- /cargo/src/lib/crypto_pairing.rs: -------------------------------------------------------------------------------- 1 | ../crypto_pairing.rs -------------------------------------------------------------------------------- /data.txt: -------------------------------------------------------------------------------- 1 | Punch card scheme with curve25519-dalek 2 | 3 | Performance Results (computer) 4 | Each operation is repeated for 1000 iterations, except punches, which are done 10000 times (10 punches per iteration). 5 | The server database starts with 0 used punchcards in each iteration. 6 | Numbers are cumulative over all runs, in microseconds. 7 | Server setup: 18590 8 | Client setup: 65722 9 | Server punch: 1343669 10 | Client punch: 3123742 11 | Client redeem: 65837 12 | Server redeem: 64278 13 | 14 | so the averages are (in microseconds): 15 | Server setup: 18.590 16 | Client setup: 65.722 17 | Server punch: 134.3669 18 | Client punch: 312.3742 19 | Client redeem: 65.837 20 | Server redeem: 64.278 21 | 22 | When I increased the starting database size to 1M, I got these numbers 23 | Server setup: 27371 24 | Client setup: 85662 25 | Server punch: 1562951 26 | Client punch: 3497363 27 | Client redeem: 73585 28 | Server redeem: 72136 29 | The only one whose performance should be affected by the database size is server redeem, but it does not look different relative to the other numbers (the results are generally high variance). This is not surprising because the only DB-dependent operation is the hash table lookup. 30 | 31 | 32 | Performance Results (Google Pixel) 33 | Each operation is repeated for 1000 iterations, except punches, which are done 10000 times (10 punches per iteration). 34 | The server database starts with 0 used punchcards in each iteration. 35 | Numbers are cumulative over all runs, in microseconds. 36 | Server setup: 304114 37 | Client setup: 939123 38 | Server punch: 19388147 39 | Client punch: 43142327 40 | Client redeem: 889866 41 | Server redeem: 949928 42 | 43 | so the averages are (in microseconds): 44 | Server setup: 304.114 45 | Client setup: 939.123 46 | Server punch: 1938.8147 47 | Client punch: 4314.2327 48 | Client redeem: 889.866 49 | Server redeem: 949.928 50 | 51 | 52 | Communication costs (for messages sent in protocol) 53 | Server setup: 32 bytes (g^secret) 54 | Client setup: none 55 | Client punch: 32 bytes (the punchcard group element) 56 | Server punch: 128 bytes (new group element and proof which has 2 group elements and a scalar, 32 bytes each) 57 | Client redeem: 64 bytes (the final card and the secret used to make the card, 32 bytes each) 58 | Server redeem: none 59 | 60 | On server, 61 | Time for lookup in hashset of 1 million entries is <1 microsecond (about .2-.3 microseconds) 62 | Time for exponentiation is about 50 microseconds (usually between 50 and 55) 63 | so to do 1M exponentiations (one for each previously used card) would probably be about 50 seconds. The speedup is about 8 orders of magnitude. 64 | 65 | Punch card scheme with pairing-plus (BLS12-381) 66 | 67 | Performance Results for BLS12_381 group with merging (computer) 68 | Each operation is repeated for 100 iterations, except punches, which are done 1000 times (10 punches per iteration). 69 | The server database starts with 0 used punchcards in each iteration. 70 | Numbers are cumulative over all runs, in microseconds. 71 | Server setup: 109839 72 | Client setup: 278976 73 | Server punch: 4327845 74 | Client punch: 10851089 75 | Client redeem: 305215 76 | Server redeem: 400271 77 | 78 | so the averages are (in _milliseconds_): 79 | Server setup: 1.09 80 | Client setup: 2.79 81 | Server punch: 4.33 82 | Client punch: 10.85 83 | Client redeem: 3.05 84 | Server redeem: 4.00 85 | 86 | Performance Results for BLS12_381 group with merging (Google Pixel) 87 | Each operation is repeated for 100 iterations, except punches, which are done 1000 times (10 punches per iteration). 88 | The server database starts with 0 used punchcards in each iteration. 89 | Numbers are cumulative over all runs, in microseconds. 90 | Server setup: 1332493 91 | Client setup: 3496631 92 | Server punch: 54449731 93 | Client punch: 137793866 94 | Client redeem: 3643494 95 | Server redeem: 4810848 96 | 97 | so the averages are (in _milliseconds_): 98 | Server setup: 13.32 99 | Client setup: 34.97 100 | Server punch: 54.45 101 | Client punch: 137.79 102 | Client redeem: 36.43 103 | Server redeem: 48.11 104 | 105 | Communication costs (for messages sent in protocol) 106 | Server setup: 144 bytes (g^secret for both groups == 48 + 96) 107 | Client setup: none 108 | Client punch: 144 bytes (the 2 punchcard group elements) 109 | Server punch: 496 bytes (2 new group elements and 2 proofs which have 2 group elements and a scalar = 144 + (96 + 32) + (192 + 32) = 496) 110 | Client redeem: 640 bytes (the final card and the secrets used to make the cards, 32 bytes each secret, 576 bytes for final card) 111 | Server redeem: none 112 | 113 | On server, 114 | Time for exponentiation in G1 is about 250 microseconds 115 | Time for exponentiation in G2 is aobut 800 microseconds 116 | Time for pairing is about 2 milliseconds 117 | --------------------------------------------------------------------------------