├── .gitignore ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── jni │ ├── Android.mk │ ├── Application.mk │ ├── curve25519-donna.c │ ├── curve25519-donna.h │ ├── curve25519-jni.c │ └── ed25519 │ │ ├── additions │ │ ├── compare.c │ │ ├── compare.h │ │ ├── crypto_additions.h │ │ ├── crypto_hash_sha512.h │ │ ├── curve_sigs.c │ │ ├── curve_sigs.h │ │ ├── elligator.c │ │ ├── fe_isequal.c │ │ ├── fe_isreduced.c │ │ ├── fe_mont_rhs.c │ │ ├── fe_montx_to_edy.c │ │ ├── fe_sqrt.c │ │ ├── ge_isneutral.c │ │ ├── ge_montx_to_p3.c │ │ ├── ge_neg.c │ │ ├── ge_p3_to_montx.c │ │ ├── ge_scalarmult.c │ │ ├── ge_scalarmult_cofactor.c │ │ ├── generalized │ │ │ ├── ge_p3_add.c │ │ │ ├── gen_constants.h │ │ │ ├── gen_crypto_additions.h │ │ │ ├── gen_eddsa.c │ │ │ ├── gen_eddsa.h │ │ │ ├── gen_labelset.c │ │ │ ├── gen_labelset.h │ │ │ ├── gen_veddsa.c │ │ │ ├── gen_veddsa.h │ │ │ ├── gen_x.c │ │ │ ├── gen_x.h │ │ │ ├── point_isreduced.c │ │ │ └── sc_isreduced.c │ │ ├── keygen.c │ │ ├── keygen.h │ │ ├── open_modified.c │ │ ├── sc_clamp.c │ │ ├── sc_cmov.c │ │ ├── sc_neg.c │ │ ├── sign_modified.c │ │ ├── utility.c │ │ ├── utility.h │ │ ├── xeddsa.c │ │ ├── xeddsa.h │ │ ├── zeroize.c │ │ └── zeroize.h │ │ ├── base.h │ │ ├── base2.h │ │ ├── d.h │ │ ├── d2.h │ │ ├── fe.h │ │ ├── fe_0.c │ │ ├── fe_1.c │ │ ├── fe_add.c │ │ ├── fe_cmov.c │ │ ├── fe_copy.c │ │ ├── fe_frombytes.c │ │ ├── fe_invert.c │ │ ├── fe_isnegative.c │ │ ├── fe_isnonzero.c │ │ ├── fe_mul.c │ │ ├── fe_neg.c │ │ ├── fe_pow22523.c │ │ ├── fe_sq.c │ │ ├── fe_sq2.c │ │ ├── fe_sub.c │ │ ├── fe_tobytes.c │ │ ├── ge.h │ │ ├── ge_add.c │ │ ├── ge_add.h │ │ ├── ge_double_scalarmult.c │ │ ├── ge_frombytes.c │ │ ├── ge_madd.c │ │ ├── ge_madd.h │ │ ├── ge_msub.c │ │ ├── ge_msub.h │ │ ├── ge_p1p1_to_p2.c │ │ ├── ge_p1p1_to_p3.c │ │ ├── ge_p2_0.c │ │ ├── ge_p2_dbl.c │ │ ├── ge_p2_dbl.h │ │ ├── ge_p3_0.c │ │ ├── ge_p3_dbl.c │ │ ├── ge_p3_to_cached.c │ │ ├── ge_p3_to_p2.c │ │ ├── ge_p3_tobytes.c │ │ ├── ge_precomp_0.c │ │ ├── ge_scalarmult_base.c │ │ ├── ge_sub.c │ │ ├── ge_sub.h │ │ ├── ge_tobytes.c │ │ ├── nacl_includes │ │ ├── crypto_int32.h │ │ ├── crypto_int64.h │ │ ├── crypto_sign.h │ │ ├── crypto_sign_edwards25519sha512batch.h │ │ ├── crypto_uint32.h │ │ ├── crypto_uint64.h │ │ └── crypto_verify_32.h │ │ ├── nacl_sha512 │ │ ├── blocks.c │ │ └── hash.c │ │ ├── open.c │ │ ├── pow22523.h │ │ ├── pow225521.h │ │ ├── sc.h │ │ ├── sc_muladd.c │ │ ├── sc_reduce.c │ │ ├── sign.c │ │ ├── sqrtm1.h │ │ └── tests │ │ ├── internal_fast_tests.c │ │ ├── internal_fast_tests.h │ │ ├── internal_slow_tests.c │ │ └── internal_slow_tests.h ├── libs │ ├── arm64-v8a │ │ └── libcurve25519.so │ ├── armeabi-v7a │ │ └── libcurve25519.so │ ├── armeabi │ │ └── libcurve25519.so │ ├── mips │ │ └── libcurve25519.so │ ├── x86 │ │ └── libcurve25519.so │ └── x86_64 │ │ └── libcurve25519.so └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── whispersystems │ │ └── curve25519 │ │ ├── NativeCurve25519ProviderTest.java │ │ └── NativeCurve25519Test.java │ └── main │ └── AndroidManifest.xml ├── build.gradle ├── common ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── whispersystems │ └── curve25519 │ ├── BaseJavaCurve25519Provider.java │ ├── Curve25519.java │ ├── Curve25519KeyPair.java │ ├── Curve25519Provider.java │ ├── NoSuchProviderException.java │ ├── SecureRandomProvider.java │ ├── VrfSignatureVerificationFailedException.java │ └── java │ ├── Arrays.java │ ├── Sha512.java │ ├── crypto_verify_32.java │ ├── curve_sigs.java │ ├── fe_0.java │ ├── fe_1.java │ ├── fe_add.java │ ├── fe_cmov.java │ ├── fe_copy.java │ ├── fe_cswap.java │ ├── fe_frombytes.java │ ├── fe_invert.java │ ├── fe_isnegative.java │ ├── fe_isnonzero.java │ ├── fe_mul.java │ ├── fe_mul121666.java │ ├── fe_neg.java │ ├── fe_pow22523.java │ ├── fe_sq.java │ ├── fe_sq2.java │ ├── fe_sub.java │ ├── fe_tobytes.java │ ├── ge_add.java │ ├── ge_cached.java │ ├── ge_double_scalarmult.java │ ├── ge_frombytes.java │ ├── ge_madd.java │ ├── ge_msub.java │ ├── ge_p1p1.java │ ├── ge_p1p1_to_p2.java │ ├── ge_p1p1_to_p3.java │ ├── ge_p2.java │ ├── ge_p2_0.java │ ├── ge_p2_dbl.java │ ├── ge_p3.java │ ├── ge_p3_0.java │ ├── ge_p3_dbl.java │ ├── ge_p3_to_cached.java │ ├── ge_p3_to_p2.java │ ├── ge_p3_tobytes.java │ ├── ge_precomp.java │ ├── ge_precomp_0.java │ ├── ge_precomp_base_0_7.java │ ├── ge_precomp_base_16_23.java │ ├── ge_precomp_base_24_31.java │ ├── ge_precomp_base_8_15.java │ ├── ge_scalarmult_base.java │ ├── ge_sub.java │ ├── ge_tobytes.java │ ├── open.java │ ├── sc_muladd.java │ ├── sc_reduce.java │ ├── scalarmult.java │ └── sign_modified.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── j2me ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── whispersystems │ │ └── curve25519 │ │ ├── BouncyCastleSha512Provider.java │ │ ├── J2meCurve25519Provider.java │ │ └── NullSecureRandomProvider.java │ └── test │ └── java │ └── org │ └── whispersystems │ └── curve25519 │ ├── FakeSecureRandomProvider.java │ ├── J2meCurve25519ProviderTest.java │ └── J2meCurve25519Test.java ├── java ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── whispersystems │ │ └── curve25519 │ │ ├── JCESecureRandomProvider.java │ │ ├── JCESha512Provider.java │ │ ├── JavaCurve25519Provider.java │ │ ├── NativeCurve25519Provider.java │ │ └── OpportunisticCurve25519Provider.java │ └── test │ └── java │ └── org │ └── whispersystems │ └── curve25519 │ ├── JavaCurve25519ProviderTest.java │ └── JavaCurve25519Test.java ├── settings.gradle └── tests ├── build.gradle └── src └── main └── java └── org └── whispersystems └── curve25519 ├── Curve25519ProviderTest.java └── Curve25519Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .idea/ 3 | *.iml 4 | obj/ 5 | build/ 6 | .gradle/ 7 | local.properties 8 | gradle.properties 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # curve25519-java 2 | 3 | A Java Curve25519 implementation that is backed by native code when available, and 4 | pure Java when a native library is not available. There is also a J2ME build variant. 5 | 6 | ## Installing 7 | 8 | To use on Android: 9 | 10 | ``` 11 | dependencies { 12 | compile 'org.whispersystems:curve25519-android:(latest version number here)' 13 | } 14 | ``` 15 | 16 | To use from pure Java: 17 | 18 | ``` 19 | 20 | org.whispersystems 21 | curve25519-java 22 | (latest version number here) 23 | 24 | ``` 25 | 26 | To use from J2ME: 27 | 28 | ``` 29 | 30 | org.whispersystems 31 | curve25519-j2me 32 | (latest version number here) 33 | 34 | ``` 35 | 36 | 37 | The Android artifact is an AAR that contains an NDK-backed native implementation, while 38 | the Java artifact is a JAR that only contains the pure-Java Curve25519 provider. 39 | 40 | ## Using 41 | 42 | ## Obtaining an instance 43 | 44 | The caller needs to specify a `provider` when obtaining a Curve25519 instance. There are 45 | four built in providers: 46 | 47 | 1. `Curve25519.NATIVE` -- This is a JNI backed provider. 48 | 1. `Curve25519.JAVA` -- This is a pure Java 7 backed provider. 49 | 1. `Curve25519.J2ME` -- This is a J2ME compatible provider. 50 | 1. `Curve25519.BEST` -- This is a provider that attempts to use `NATIVE`, 51 | but falls back to `JAVA` if the former is unavailable. 52 | 53 | The caller specifies a provider during instance creation: 54 | 55 | ``` 56 | Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST); 57 | ``` 58 | 59 | Since J2ME doesn't have built-in `SecureRandom` support, J2ME users need to supply their 60 | own source of `SecureRandom` by implementing the `SecureRandomProvider` interface and 61 | passing it in: 62 | 63 | ``` 64 | Curve25519 cipher = Curve25519.getInstance(Curve25519.J2ME, new MySecureRandomProvider()); 65 | ``` 66 | 67 | ### Generating a Curve25519 keypair: 68 | 69 | ``` 70 | Curve25519KeyPair keyPair = Curve25519.getInstance(Curve25519.BEST).generateKeyPair(); 71 | ``` 72 | 73 | ### Calculating a shared secret: 74 | 75 | ``` 76 | Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST); 77 | byte[] sharedSecret = cipher.calculateAgreement(publicKey, privateKey); 78 | ``` 79 | 80 | ### Calculating a signature: 81 | 82 | ``` 83 | Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST); 84 | byte[] signature = cipher.calculateSignature(secureRandom, privateKey, message); 85 | ``` 86 | 87 | ### Verifying a signature: 88 | 89 | ``` 90 | Curve25519 cipher = Curve25519.getInstance(Curve25519.BEST); 91 | boolean validSignature = cipher.verifySignature(publicKey, message, signature); 92 | ``` 93 | 94 | ## License 95 | 96 | Copyright 2015 Open Whisper Systems 97 | 98 | Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html 99 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:2.2.0' 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.library' 12 | apply plugin: 'maven' 13 | apply plugin: 'signing' 14 | 15 | archivesBaseName = "curve25519-android" 16 | version = version_number 17 | group = group_info 18 | 19 | android { 20 | compileSdkVersion 21 21 | buildToolsVersion "21.1.2" 22 | 23 | sourceSets { 24 | main { 25 | jniLibs.srcDirs = ['libs'] 26 | } 27 | } 28 | 29 | libraryVariants.all { variant -> 30 | variant.outputs.each { output -> 31 | def outputFile = output.outputFile 32 | if (outputFile != null && outputFile.name.endsWith('.aar')) { 33 | def fileName = "${archivesBaseName}-${version}.aar" 34 | output.outputFile = new File(outputFile.parent, fileName) 35 | } 36 | } 37 | } 38 | } 39 | 40 | repositories { 41 | mavenCentral() 42 | } 43 | 44 | dependencies { 45 | compile project(':java') 46 | 47 | androidTestCompile (project(":tests")) { 48 | exclude module: 'junit' 49 | } 50 | } 51 | 52 | signing { 53 | required { has("release") && gradle.taskGraph.hasTask("uploadArchives") } 54 | sign configurations.archives 55 | } 56 | 57 | uploadArchives { 58 | configuration = configurations.archives 59 | repositories.mavenDeployer { 60 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 61 | 62 | repository(url: sonatypeRepo) { 63 | authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword) 64 | } 65 | 66 | pom.project { 67 | name 'curve25519-android' 68 | packaging 'aar' 69 | description 'Curve25519 library for Android' 70 | url 'https://github.com/WhisperSystems/curve25519-java' 71 | 72 | scm { 73 | url 'scm:git@github.com:WhisperSystems/curve25519-java.git' 74 | connection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 75 | developerConnection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 76 | } 77 | 78 | licenses { 79 | license { 80 | name 'GPLv3' 81 | url 'https://www.gnu.org/licenses/gpl-3.0.txt' 82 | distribution 'repo' 83 | } 84 | } 85 | 86 | developers { 87 | developer { 88 | name 'Trevor Perrin' 89 | name 'Moxie Marlinspike' 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | task installArchives(type: Upload) { 97 | description "Installs the artifacts to the local Maven repository." 98 | configuration = configurations['archives'] 99 | repositories { 100 | mavenDeployer { 101 | repository url: "file://${System.properties['user.home']}/.m2/repository" 102 | } 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /android/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := libcurve25519-donna 6 | LOCAL_SRC_FILES := curve25519-donna.c 7 | 8 | include $(BUILD_STATIC_LIBRARY) 9 | 10 | include $(CLEAR_VARS) 11 | 12 | LOCAL_MODULE := libcurve25519-ref10 13 | LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) \ 14 | $(wildcard ed25519/additions/generalized/*.c) $(wildcard ed25519/nacl_sha512/*.c) \ 15 | ed25519/tests/internal_fast_tests.c 16 | 17 | LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/additions/generalized ed25519/tests ed25519/sha512 ed25519 18 | 19 | include $(BUILD_STATIC_LIBRARY) 20 | 21 | include $(CLEAR_VARS) 22 | 23 | LOCAL_MODULE := libcurve25519 24 | LOCAL_SRC_FILES := curve25519-jni.c 25 | LOCAL_C_INCLUDES := ed25519/additions ed25519/additions/generalized ed25519/tests 26 | 27 | LOCAL_STATIC_LIBRARIES := libcurve25519-donna libcurve25519-ref10 28 | 29 | include $(BUILD_SHARED_LIBRARY) 30 | 31 | -------------------------------------------------------------------------------- /android/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 2 | -------------------------------------------------------------------------------- /android/jni/curve25519-donna.h: -------------------------------------------------------------------------------- 1 | #ifndef CURVE25519_DONNA_H 2 | #define CURVE25519_DONNA_H 3 | 4 | extern int curve25519_donna(uint8_t *, const uint8_t *, const uint8_t *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/compare.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "compare.h" 3 | 4 | /* Const-time comparison from SUPERCOP, but here it's only used for 5 | signature verification, so doesn't need to be const-time. But 6 | copied the nacl version anyways. */ 7 | int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y) 8 | { 9 | unsigned int differentbits = 0; 10 | #define F(i) differentbits |= x[i] ^ y[i]; 11 | F(0) 12 | F(1) 13 | F(2) 14 | F(3) 15 | F(4) 16 | F(5) 17 | F(6) 18 | F(7) 19 | F(8) 20 | F(9) 21 | F(10) 22 | F(11) 23 | F(12) 24 | F(13) 25 | F(14) 26 | F(15) 27 | F(16) 28 | F(17) 29 | F(18) 30 | F(19) 31 | F(20) 32 | F(21) 33 | F(22) 34 | F(23) 35 | F(24) 36 | F(25) 37 | F(26) 38 | F(27) 39 | F(28) 40 | F(29) 41 | F(30) 42 | F(31) 43 | return (1 & ((differentbits - 1) >> 8)) - 1; 44 | } 45 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/compare.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMPARE_H__ 2 | #define __COMPARE_H__ 3 | 4 | int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/crypto_additions.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CRYPTO_ADDITIONS__ 3 | #define __CRYPTO_ADDITIONS__ 4 | 5 | #include "crypto_uint32.h" 6 | #include "fe.h" 7 | #include "ge.h" 8 | 9 | #define MAX_MSG_LEN 256 10 | 11 | void sc_neg(unsigned char *b, const unsigned char *a); 12 | void sc_cmov(unsigned char* f, const unsigned char* g, unsigned char b); 13 | 14 | int fe_isequal(const fe f, const fe g); 15 | int fe_isreduced(const unsigned char* s); 16 | void fe_mont_rhs(fe v2, const fe u); 17 | void fe_montx_to_edy(fe y, const fe u); 18 | void fe_sqrt(fe b, const fe a); 19 | 20 | int ge_isneutral(const ge_p3* q); 21 | void ge_neg(ge_p3* r, const ge_p3 *p); 22 | void ge_montx_to_p3(ge_p3* p, const fe u, const unsigned char ed_sign_bit); 23 | void ge_p3_to_montx(fe u, const ge_p3 *p); 24 | void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A); 25 | void ge_scalarmult_cofactor(ge_p3 *q, const ge_p3 *p); 26 | 27 | void elligator(fe u, const fe r); 28 | void hash_to_point(ge_p3* p, const unsigned char* msg, const unsigned long in_len); 29 | 30 | int crypto_sign_modified( 31 | unsigned char *sm, 32 | const unsigned char *m,unsigned long long mlen, 33 | const unsigned char *sk, /* Curve/Ed25519 private key */ 34 | const unsigned char *pk, /* Ed25519 public key */ 35 | const unsigned char *random /* 64 bytes random to hash into nonce */ 36 | ); 37 | 38 | int crypto_sign_open_modified( 39 | unsigned char *m, 40 | const unsigned char *sm,unsigned long long smlen, 41 | const unsigned char *pk 42 | ); 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/crypto_hash_sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_hash_sha512_H 2 | #define crypto_hash_sha512_H 3 | 4 | extern int crypto_hash_sha512(unsigned char *,const unsigned char *,unsigned long long); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/curve_sigs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ge.h" 4 | #include "curve_sigs.h" 5 | #include "crypto_sign.h" 6 | #include "crypto_additions.h" 7 | 8 | int curve25519_sign(unsigned char* signature_out, 9 | const unsigned char* curve25519_privkey, 10 | const unsigned char* msg, const unsigned long msg_len, 11 | const unsigned char* random) 12 | { 13 | ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ 14 | unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ 15 | unsigned char *sigbuf; /* working buffer */ 16 | unsigned char sign_bit = 0; 17 | 18 | if ((sigbuf = malloc(msg_len + 128)) == 0) { 19 | memset(signature_out, 0, 64); 20 | return -1; 21 | } 22 | 23 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 24 | ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); 25 | ge_p3_tobytes(ed_pubkey, &ed_pubkey_point); 26 | sign_bit = ed_pubkey[31] & 0x80; 27 | 28 | /* Perform an Ed25519 signature with explicit private key */ 29 | crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey, 30 | ed_pubkey, random); 31 | memmove(signature_out, sigbuf, 64); 32 | 33 | /* Encode the sign bit into signature (in unused high bit of S) */ 34 | signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ 35 | signature_out[63] |= sign_bit; 36 | 37 | free(sigbuf); 38 | return 0; 39 | } 40 | 41 | int curve25519_verify(const unsigned char* signature, 42 | const unsigned char* curve25519_pubkey, 43 | const unsigned char* msg, const unsigned long msg_len) 44 | { 45 | fe u; 46 | fe y; 47 | unsigned char ed_pubkey[32]; 48 | unsigned char *verifybuf = NULL; /* working buffer */ 49 | unsigned char *verifybuf2 = NULL; /* working buffer #2 */ 50 | int result; 51 | 52 | if ((verifybuf = malloc(msg_len + 64)) == 0) { 53 | result = -1; 54 | goto err; 55 | } 56 | 57 | if ((verifybuf2 = malloc(msg_len + 64)) == 0) { 58 | result = -1; 59 | goto err; 60 | } 61 | 62 | /* Convert the Curve25519 public key into an Ed25519 public key. In 63 | particular, convert Curve25519's "montgomery" x-coordinate (u) into an 64 | Ed25519 "edwards" y-coordinate: 65 | 66 | y = (u - 1) / (u + 1) 67 | 68 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 69 | 70 | Then move the sign bit into the pubkey from the signature. 71 | */ 72 | fe_frombytes(u, curve25519_pubkey); 73 | fe_montx_to_edy(y, u); 74 | fe_tobytes(ed_pubkey, y); 75 | 76 | /* Copy the sign bit, and remove it from signature */ 77 | ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ 78 | ed_pubkey[31] |= (signature[63] & 0x80); 79 | memmove(verifybuf, signature, 64); 80 | verifybuf[63] &= 0x7F; 81 | 82 | memmove(verifybuf+64, msg, msg_len); 83 | 84 | /* Then perform a normal Ed25519 verification, return 0 on success */ 85 | /* The below call has a strange API: */ 86 | /* verifybuf = R || S || message */ 87 | /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets 88 | replaced with pubkey for hashing */ 89 | result = crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey); 90 | 91 | err: 92 | 93 | if (verifybuf != NULL) { 94 | free(verifybuf); 95 | } 96 | 97 | if (verifybuf2 != NULL) { 98 | free(verifybuf2); 99 | } 100 | 101 | return result; 102 | } 103 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/curve_sigs.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CURVE_SIGS_H__ 3 | #define __CURVE_SIGS_H__ 4 | 5 | /* returns 0 on success */ 6 | int curve25519_sign(unsigned char* signature_out, /* 64 bytes */ 7 | const unsigned char* curve25519_privkey, /* 32 bytes */ 8 | const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */ 9 | const unsigned char* random); /* 64 bytes */ 10 | 11 | /* returns 0 on success */ 12 | int curve25519_verify(const unsigned char* signature, /* 64 bytes */ 13 | const unsigned char* curve25519_pubkey, /* 32 bytes */ 14 | const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */ 15 | 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/elligator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fe.h" 3 | #include "ge.h" 4 | #include "crypto_uint32.h" 5 | #include "crypto_hash_sha512.h" 6 | #include "crypto_additions.h" 7 | 8 | unsigned int legendre_is_nonsquare(fe in) 9 | { 10 | fe temp; 11 | unsigned char bytes[32]; 12 | fe_pow22523(temp, in); /* temp = in^((q-5)/8) */ 13 | fe_sq(temp, temp); /* in^((q-5)/4) */ 14 | fe_sq(temp, temp); /* in^((q-5)/2) */ 15 | fe_mul(temp, temp, in); /* in^((q-3)/2) */ 16 | fe_mul(temp, temp, in); /* in^((q-1)/2) */ 17 | 18 | /* temp is now the Legendre symbol: 19 | * 1 = square 20 | * 0 = input is zero 21 | * -1 = nonsquare 22 | */ 23 | fe_tobytes(bytes, temp); 24 | return 1 & bytes[31]; 25 | } 26 | 27 | void elligator(fe u, const fe r) 28 | { 29 | /* r = input 30 | * x = -A/(1+2r^2) # 2 is nonsquare 31 | * e = (x^3 + Ax^2 + x)^((q-1)/2) # legendre symbol 32 | * if e == 1 (square) or e == 0 (because x == 0 and 2r^2 + 1 == 0) 33 | * u = x 34 | * if e == -1 (nonsquare) 35 | * u = -x - A 36 | */ 37 | fe A, one, twor2, twor2plus1, twor2plus1inv; 38 | fe x, e, Atemp, uneg; 39 | unsigned int nonsquare; 40 | 41 | fe_1(one); 42 | fe_0(A); 43 | A[0] = 486662; /* A = 486662 */ 44 | 45 | fe_sq2(twor2, r); /* 2r^2 */ 46 | fe_add(twor2plus1, twor2, one); /* 1+2r^2 */ 47 | fe_invert(twor2plus1inv, twor2plus1); /* 1/(1+2r^2) */ 48 | fe_mul(x, twor2plus1inv, A); /* A/(1+2r^2) */ 49 | fe_neg(x, x); /* x = -A/(1+2r^2) */ 50 | 51 | fe_mont_rhs(e, x); /* e = x^3 + Ax^2 + x */ 52 | nonsquare = legendre_is_nonsquare(e); 53 | 54 | fe_0(Atemp); 55 | fe_cmov(Atemp, A, nonsquare); /* 0, or A if nonsquare */ 56 | fe_add(u, x, Atemp); /* x, or x+A if nonsquare */ 57 | fe_neg(uneg, u); /* -x, or -x-A if nonsquare */ 58 | fe_cmov(u, uneg, nonsquare); /* x, or -x-A if nonsquare */ 59 | } 60 | 61 | void hash_to_point(ge_p3* p, const unsigned char* in, const unsigned long in_len) 62 | { 63 | unsigned char hash[64]; 64 | fe h, u; 65 | unsigned char sign_bit; 66 | ge_p3 p3; 67 | 68 | crypto_hash_sha512(hash, in, in_len); 69 | 70 | /* take the high bit as Edwards sign bit */ 71 | sign_bit = (hash[31] & 0x80) >> 7; 72 | hash[31] &= 0x7F; 73 | fe_frombytes(h, hash); 74 | elligator(u, h); 75 | 76 | ge_montx_to_p3(&p3, u, sign_bit); 77 | ge_scalarmult_cofactor(p, &p3); 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/fe_isequal.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "crypto_verify_32.h" 3 | 4 | /* 5 | return 1 if f == g 6 | return 0 if f != g 7 | */ 8 | 9 | int fe_isequal(const fe f, const fe g) 10 | { 11 | fe h; 12 | fe_sub(h, f, g); 13 | return 1 ^ (1 & (fe_isnonzero(h) >> 8)); 14 | } 15 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/fe_isreduced.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "crypto_verify_32.h" 3 | 4 | int fe_isreduced(const unsigned char* s) 5 | { 6 | fe f; 7 | unsigned char strict[32]; 8 | 9 | fe_frombytes(f, s); 10 | fe_tobytes(strict, f); 11 | if (crypto_verify_32(strict, s) != 0) 12 | return 0; 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/fe_mont_rhs.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_mont_rhs(fe v2, fe u) { 4 | fe A, one; 5 | fe u2, Au, inner; 6 | 7 | fe_1(one); 8 | fe_0(A); 9 | A[0] = 486662; /* A = 486662 */ 10 | 11 | fe_sq(u2, u); /* u^2 */ 12 | fe_mul(Au, A, u); /* Au */ 13 | fe_add(inner, u2, Au); /* u^2 + Au */ 14 | fe_add(inner, inner, one); /* u^2 + Au + 1 */ 15 | fe_mul(v2, u, inner); /* u(u^2 + Au + 1) */ 16 | } 17 | 18 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/fe_montx_to_edy.c: -------------------------------------------------------------------------------- 1 | 2 | #include "fe.h" 3 | #include "crypto_additions.h" 4 | 5 | void fe_montx_to_edy(fe y, const fe u) 6 | { 7 | /* 8 | y = (u - 1) / (u + 1) 9 | 10 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 11 | */ 12 | fe one, um1, up1; 13 | 14 | fe_1(one); 15 | fe_sub(um1, u, one); 16 | fe_add(up1, u, one); 17 | fe_invert(up1, up1); 18 | fe_mul(y, um1, up1); 19 | } 20 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/fe_sqrt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fe.h" 3 | #include "crypto_additions.h" 4 | 5 | /* sqrt(-1) */ 6 | static unsigned char i_bytes[32] = { 7 | 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, 8 | 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, 9 | 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b, 10 | 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b 11 | }; 12 | 13 | /* Preconditions: a is square or zero */ 14 | 15 | void fe_sqrt(fe out, const fe a) 16 | { 17 | fe exp, b, b2, bi, i; 18 | #ifndef NDEBUG 19 | fe legendre, zero, one; 20 | #endif 21 | 22 | fe_frombytes(i, i_bytes); 23 | fe_pow22523(exp, a); /* b = a^(q-5)/8 */ 24 | 25 | /* PRECONDITION: legendre symbol == 1 (square) or 0 (a == zero) */ 26 | #ifndef NDEBUG 27 | fe_sq(legendre, exp); /* in^((q-5)/4) */ 28 | fe_sq(legendre, legendre); /* in^((q-5)/2) */ 29 | fe_mul(legendre, legendre, a); /* in^((q-3)/2) */ 30 | fe_mul(legendre, legendre, a); /* in^((q-1)/2) */ 31 | 32 | fe_0(zero); 33 | fe_1(one); 34 | assert(fe_isequal(legendre, zero) || fe_isequal(legendre, one)); 35 | #endif 36 | 37 | fe_mul(b, a, exp); /* b = a * a^(q-5)/8 */ 38 | fe_sq(b2, b); /* b^2 = a * a^(q-1)/4 */ 39 | 40 | /* note b^4 == a^2, so b^2 == a or -a 41 | * if b^2 != a, multiply it by sqrt(-1) */ 42 | fe_mul(bi, b, i); 43 | fe_cmov(b, bi, 1 ^ fe_isequal(b2, a)); 44 | fe_copy(out, b); 45 | 46 | /* PRECONDITION: out^2 == a */ 47 | #ifndef NDEBUG 48 | fe_sq(b2, out); 49 | assert(fe_isequal(a, b2)); 50 | #endif 51 | } 52 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_isneutral.c: -------------------------------------------------------------------------------- 1 | #include "crypto_additions.h" 2 | #include "ge.h" 3 | 4 | /* 5 | return 1 if p is the neutral point 6 | return 0 otherwise 7 | */ 8 | 9 | int ge_isneutral(const ge_p3 *p) 10 | { 11 | fe zero; 12 | fe_0(zero); 13 | 14 | /* Check if p == neutral element == (0, 1) */ 15 | return (fe_isequal(p->X, zero) & fe_isequal(p->Y, p->Z)); 16 | } 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_montx_to_p3.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "ge.h" 3 | #include "assert.h" 4 | #include "crypto_additions.h" 5 | #include "utility.h" 6 | 7 | /* sqrt(-(A+2)) */ 8 | static unsigned char A_bytes[32] = { 9 | 0x06, 0x7e, 0x45, 0xff, 0xaa, 0x04, 0x6e, 0xcc, 10 | 0x82, 0x1a, 0x7d, 0x4b, 0xd1, 0xd3, 0xa1, 0xc5, 11 | 0x7e, 0x4f, 0xfc, 0x03, 0xdc, 0x08, 0x7b, 0xd2, 12 | 0xbb, 0x06, 0xa0, 0x60, 0xf4, 0xed, 0x26, 0x0f 13 | }; 14 | 15 | void ge_montx_to_p3(ge_p3* p, const fe u, const unsigned char ed_sign_bit) 16 | { 17 | fe x, y, A, v, v2, iv, nx; 18 | 19 | fe_frombytes(A, A_bytes); 20 | 21 | /* given u, recover edwards y */ 22 | /* given u, recover v */ 23 | /* given u and v, recover edwards x */ 24 | 25 | fe_montx_to_edy(y, u); /* y = (u - 1) / (u + 1) */ 26 | 27 | fe_mont_rhs(v2, u); /* v^2 = u(u^2 + Au + 1) */ 28 | fe_sqrt(v, v2); /* v = sqrt(v^2) */ 29 | 30 | fe_mul(x, u, A); /* x = u * sqrt(-(A+2)) */ 31 | fe_invert(iv, v); /* 1/v */ 32 | fe_mul(x, x, iv); /* x = (u/v) * sqrt(-(A+2)) */ 33 | 34 | fe_neg(nx, x); /* negate x to match sign bit */ 35 | fe_cmov(x, nx, fe_isnegative(x) ^ ed_sign_bit); 36 | 37 | fe_copy(p->X, x); 38 | fe_copy(p->Y, y); 39 | fe_1(p->Z); 40 | fe_mul(p->T, p->X, p->Y); 41 | 42 | /* POSTCONDITION: check that p->X and p->Y satisfy the Ed curve equation */ 43 | /* -x^2 + y^2 = 1 + dx^2y^2 */ 44 | #ifndef NDEBUG 45 | { 46 | fe one, d, x2, y2, x2y2, dx2y2; 47 | 48 | unsigned char dbytes[32] = { 49 | 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 50 | 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, 51 | 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, 52 | 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 53 | }; 54 | 55 | fe_frombytes(d, dbytes); 56 | fe_1(one); 57 | fe_sq(x2, p->X); /* x^2 */ 58 | fe_sq(y2, p->Y); /* y^2 */ 59 | 60 | fe_mul(dx2y2, x2, y2); /* x^2y^2 */ 61 | fe_mul(dx2y2, dx2y2, d); /* dx^2y^2 */ 62 | fe_add(dx2y2, dx2y2, one); /* dx^2y^2 + 1 */ 63 | 64 | fe_neg(x2y2, x2); /* -x^2 */ 65 | fe_add(x2y2, x2y2, y2); /* -x^2 + y^2 */ 66 | 67 | assert(fe_isequal(x2y2, dx2y2)); 68 | } 69 | #endif 70 | } 71 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_neg.c: -------------------------------------------------------------------------------- 1 | #include "crypto_additions.h" 2 | #include "ge.h" 3 | 4 | /* 5 | return r = -p 6 | */ 7 | 8 | 9 | void ge_neg(ge_p3* r, const ge_p3 *p) 10 | { 11 | fe_neg(r->X, p->X); 12 | fe_copy(r->Y, p->Y); 13 | fe_copy(r->Z, p->Z); 14 | fe_neg(r->T, p->T); 15 | } 16 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_p3_to_montx.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "crypto_additions.h" 3 | 4 | void ge_p3_to_montx(fe u, const ge_p3 *ed) 5 | { 6 | /* 7 | u = (y + 1) / (1 - y) 8 | or 9 | u = (y + z) / (z - y) 10 | 11 | NOTE: y=1 is converted to u=0 since fe_invert is mod-exp 12 | */ 13 | 14 | fe y_plus_one, one_minus_y, inv_one_minus_y; 15 | 16 | fe_add(y_plus_one, ed->Y, ed->Z); 17 | fe_sub(one_minus_y, ed->Z, ed->Y); 18 | fe_invert(inv_one_minus_y, one_minus_y); 19 | fe_mul(u, y_plus_one, inv_one_minus_y); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_scalarmult.c: -------------------------------------------------------------------------------- 1 | #include "crypto_uint32.h" 2 | #include "ge.h" 3 | #include "crypto_additions.h" 4 | 5 | static unsigned char equal(signed char b,signed char c) 6 | { 7 | unsigned char ub = b; 8 | unsigned char uc = c; 9 | unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ 10 | crypto_uint32 y = x; /* 0: yes; 1..255: no */ 11 | y -= 1; /* 4294967295: yes; 0..254: no */ 12 | y >>= 31; /* 1: yes; 0: no */ 13 | return y; 14 | } 15 | 16 | static unsigned char negative(signed char b) 17 | { 18 | unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 19 | x >>= 63; /* 1: yes; 0: no */ 20 | return x; 21 | } 22 | 23 | static void cmov(ge_cached *t,const ge_cached *u,unsigned char b) 24 | { 25 | fe_cmov(t->YplusX,u->YplusX,b); 26 | fe_cmov(t->YminusX,u->YminusX,b); 27 | fe_cmov(t->Z,u->Z,b); 28 | fe_cmov(t->T2d,u->T2d,b); 29 | } 30 | 31 | static void select(ge_cached *t,const ge_cached *pre, signed char b) 32 | { 33 | ge_cached minust; 34 | unsigned char bnegative = negative(b); 35 | unsigned char babs = b - (((-bnegative) & b) << 1); 36 | 37 | fe_1(t->YplusX); 38 | fe_1(t->YminusX); 39 | fe_1(t->Z); 40 | fe_0(t->T2d); 41 | 42 | cmov(t,pre+0,equal(babs,1)); 43 | cmov(t,pre+1,equal(babs,2)); 44 | cmov(t,pre+2,equal(babs,3)); 45 | cmov(t,pre+3,equal(babs,4)); 46 | cmov(t,pre+4,equal(babs,5)); 47 | cmov(t,pre+5,equal(babs,6)); 48 | cmov(t,pre+6,equal(babs,7)); 49 | cmov(t,pre+7,equal(babs,8)); 50 | fe_copy(minust.YplusX,t->YminusX); 51 | fe_copy(minust.YminusX,t->YplusX); 52 | fe_copy(minust.Z,t->Z); 53 | fe_neg(minust.T2d,t->T2d); 54 | cmov(t,&minust,bnegative); 55 | } 56 | 57 | /* 58 | h = a * B 59 | where a = a[0]+256*a[1]+...+256^31 a[31] 60 | B is the Ed25519 base point (x,4/5) with x positive. 61 | 62 | Preconditions: 63 | a[31] <= 127 64 | */ 65 | 66 | void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A) 67 | { 68 | signed char e[64]; 69 | signed char carry; 70 | ge_p1p1 r; 71 | ge_p2 s; 72 | ge_p3 t0, t1, t2; 73 | ge_cached t, pre[8]; 74 | int i; 75 | 76 | for (i = 0;i < 32;++i) { 77 | e[2 * i + 0] = (a[i] >> 0) & 15; 78 | e[2 * i + 1] = (a[i] >> 4) & 15; 79 | } 80 | /* each e[i] is between 0 and 15 */ 81 | /* e[63] is between 0 and 7 */ 82 | 83 | carry = 0; 84 | for (i = 0;i < 63;++i) { 85 | e[i] += carry; 86 | carry = e[i] + 8; 87 | carry >>= 4; 88 | e[i] -= carry << 4; 89 | } 90 | e[63] += carry; 91 | /* each e[i] is between -8 and 8 */ 92 | 93 | // Precomputation: 94 | ge_p3_to_cached(pre+0, A); // A 95 | 96 | ge_p3_dbl(&r, A); 97 | ge_p1p1_to_p3(&t0, &r); 98 | ge_p3_to_cached(pre+1, &t0); // 2A 99 | 100 | ge_add(&r, A, pre+1); 101 | ge_p1p1_to_p3(&t1, &r); 102 | ge_p3_to_cached(pre+2, &t1); // 3A 103 | 104 | ge_p3_dbl(&r, &t0); 105 | ge_p1p1_to_p3(&t0, &r); 106 | ge_p3_to_cached(pre+3, &t0); // 4A 107 | 108 | ge_add(&r, A, pre+3); 109 | ge_p1p1_to_p3(&t2, &r); 110 | ge_p3_to_cached(pre+4, &t2); // 5A 111 | 112 | ge_p3_dbl(&r, &t1); 113 | ge_p1p1_to_p3(&t1, &r); 114 | ge_p3_to_cached(pre+5, &t1); // 6A 115 | 116 | ge_add(&r, A, pre+5); 117 | ge_p1p1_to_p3(&t1, &r); 118 | ge_p3_to_cached(pre+6, &t1); // 7A 119 | 120 | ge_p3_dbl(&r, &t0); 121 | ge_p1p1_to_p3(&t0, &r); 122 | ge_p3_to_cached(pre+7, &t0); // 8A 123 | 124 | ge_p3_0(h); 125 | 126 | for (i = 63;i > 0; i--) { 127 | select(&t,pre,e[i]); 128 | ge_add(&r, h, &t); 129 | ge_p1p1_to_p2(&s,&r); 130 | 131 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 132 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 133 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 134 | ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); 135 | 136 | } 137 | select(&t,pre,e[0]); 138 | ge_add(&r, h, &t); 139 | ge_p1p1_to_p3(h,&r); 140 | } 141 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/ge_scalarmult_cofactor.c: -------------------------------------------------------------------------------- 1 | #include "crypto_additions.h" 2 | #include "ge.h" 3 | 4 | /* 5 | return 8 * p 6 | */ 7 | 8 | void ge_scalarmult_cofactor(ge_p3 *q, const ge_p3 *p) 9 | { 10 | ge_p1p1 p1p1; 11 | ge_p2 p2; 12 | 13 | ge_p3_dbl(&p1p1, p); 14 | ge_p1p1_to_p2(&p2, &p1p1); 15 | 16 | ge_p2_dbl(&p1p1, &p2); 17 | ge_p1p1_to_p2(&p2, &p1p1); 18 | 19 | ge_p2_dbl(&p1p1, &p2); 20 | ge_p1p1_to_p3(q, &p1p1); 21 | } 22 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/ge_p3_add.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_p3_add(ge_p3 *r, const ge_p3 *p, const ge_p3 *q) 8 | { 9 | ge_cached p_cached; 10 | ge_p1p1 r_p1p1; 11 | 12 | ge_p3_to_cached(&p_cached, p); 13 | ge_add(&r_p1p1, q, &p_cached); 14 | ge_p1p1_to_p3(r, &r_p1p1); 15 | } 16 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_constants.h: -------------------------------------------------------------------------------- 1 | #ifndef _GEN_CONSTANTS_H__ 2 | #define _GEN_CONSTANTS_H__ 3 | 4 | #define LABELSETMAXLEN 512 5 | #define LABELMAXLEN 128 6 | #define BUFLEN 1024 7 | #define BLOCKLEN 128 /* SHA512 */ 8 | #define HASHLEN 64 /* SHA512 */ 9 | #define POINTLEN 32 10 | #define SCALARLEN 32 11 | #define RANDLEN 32 12 | #define SIGNATURELEN 64 13 | #define VRFSIGNATURELEN 96 14 | #define VRFOUTPUTLEN 32 15 | #define MSTART 2048 16 | #define MSGMAXLEN 1048576 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_crypto_additions.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __GEN_CRYPTO_ADDITIONS__ 3 | #define __GEN_CRYPTO_ADDITIONS__ 4 | 5 | #include "crypto_uint32.h" 6 | #include "fe.h" 7 | #include "ge.h" 8 | 9 | int sc_isreduced(const unsigned char* s); 10 | 11 | int point_isreduced(const unsigned char* p); 12 | 13 | void ge_p3_add(ge_p3 *r, const ge_p3 *p, const ge_p3 *q); 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_eddsa.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEN_EDDSA_H__ 2 | #define __GEN_EDDSA_H__ 3 | 4 | #include "ge.h" 5 | 6 | /* B: base point 7 | R: commitment (point), 8 | r: private nonce (scalar) 9 | K: encoded public key 10 | k: private key (scalar) 11 | Z: 32-bytes random 12 | M: buffer containing message, message starts at M_start, continues for M_len 13 | 14 | r = hash(B || labelset || Z || pad1 || k || pad2 || labelset || K || extra || M) (mod q) 15 | */ 16 | int generalized_commit(unsigned char* R_bytes, unsigned char* r_scalar, 17 | const unsigned char* labelset, const unsigned long labelset_len, 18 | const unsigned char* extra, const unsigned long extra_len, 19 | const unsigned char* K_bytes, const unsigned char* k_scalar, 20 | const unsigned char* Z, 21 | unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len); 22 | 23 | /* if is_labelset_empty(labelset): 24 | return hash(R || K || M) (mod q) 25 | else: 26 | return hash(B || labelset || R || labelset || K || extra || M) (mod q) 27 | */ 28 | int generalized_challenge(unsigned char* h_scalar, 29 | const unsigned char* labelset, const unsigned long labelset_len, 30 | const unsigned char* extra, const unsigned long extra_len, 31 | const unsigned char* R_bytes, 32 | const unsigned char* K_bytes, 33 | unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len); 34 | 35 | /* return r + kh (mod q) */ 36 | int generalized_prove(unsigned char* out_scalar, 37 | const unsigned char* r_scalar, 38 | const unsigned char* k_scalar, 39 | const unsigned char* h_scalar); 40 | 41 | /* R = B^s / K^h */ 42 | int generalized_solve_commitment(unsigned char* R_bytes_out, ge_p3* K_point_out, 43 | const ge_p3* B_point, const unsigned char* s_scalar, 44 | const unsigned char* K_bytes, const unsigned char* h_scalar); 45 | 46 | 47 | int generalized_eddsa_25519_sign( 48 | unsigned char* signature_out, 49 | const unsigned char* eddsa_25519_pubkey_bytes, 50 | const unsigned char* eddsa_25519_privkey_scalar, 51 | const unsigned char* msg, 52 | const unsigned long msg_len, 53 | const unsigned char* random, 54 | const unsigned char* customization_label, 55 | const unsigned long customization_label_len); 56 | 57 | int generalized_eddsa_25519_verify( 58 | const unsigned char* signature, 59 | const unsigned char* eddsa_25519_pubkey, 60 | const unsigned char* msg, 61 | const unsigned long msg_len, 62 | const unsigned char* customization_label, 63 | const unsigned long customization_label_len); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_labelset.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "gen_labelset.h" 4 | #include "gen_constants.h" 5 | 6 | const unsigned char B_bytes[] = { 7 | 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 8 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 9 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 10 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 11 | }; 12 | 13 | unsigned char* buffer_add(unsigned char* bufptr, const unsigned char* bufend, 14 | const unsigned char* in, const unsigned long in_len) 15 | { 16 | unsigned long count = 0; 17 | 18 | if (bufptr == NULL || bufend == NULL || bufptr > bufend) 19 | return NULL; 20 | if (in == NULL && in_len != 0) 21 | return NULL; 22 | if (bufend - bufptr < in_len) 23 | return NULL; 24 | 25 | for (count=0; count < in_len; count++) { 26 | if (bufptr >= bufend) 27 | return NULL; 28 | *bufptr++ = *in++; 29 | } 30 | return bufptr; 31 | } 32 | 33 | unsigned char* buffer_pad(const unsigned char* buf, unsigned char* bufptr, const unsigned char* bufend) 34 | { 35 | unsigned long count = 0; 36 | unsigned long pad_len = 0; 37 | 38 | if (buf == NULL || bufptr == NULL || bufend == NULL || bufptr >= bufend || bufptr < buf) 39 | return NULL; 40 | 41 | pad_len = (BLOCKLEN - ((bufptr-buf) % BLOCKLEN)) % BLOCKLEN; 42 | if (bufend - bufptr < pad_len) 43 | return NULL; 44 | 45 | for (count=0; count < pad_len; count++) { 46 | if (bufptr >= bufend) 47 | return NULL; 48 | *bufptr++ = 0; 49 | } 50 | return bufptr; 51 | } 52 | 53 | int labelset_new(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen, 54 | const unsigned char* protocol_name, const unsigned char protocol_name_len, 55 | const unsigned char* customization_label, const unsigned char customization_label_len) 56 | { 57 | unsigned char* bufptr; 58 | 59 | *labelset_len = 0; 60 | if (labelset == NULL) 61 | return -1; 62 | if (labelset_len == NULL) 63 | return -1; 64 | if (labelset_maxlen > LABELSETMAXLEN) 65 | return -1; 66 | if (labelset_maxlen < 3 + protocol_name_len + customization_label_len) 67 | return -1; 68 | if (protocol_name == NULL && protocol_name_len != 0) 69 | return -1; 70 | if (customization_label == NULL && customization_label_len != 0) 71 | return -1; 72 | if (protocol_name_len > LABELMAXLEN) 73 | return -1; 74 | if (customization_label_len > LABELMAXLEN) 75 | return -1; 76 | 77 | bufptr = labelset; 78 | *bufptr++ = 2; 79 | *bufptr++ = protocol_name_len; 80 | bufptr = buffer_add(bufptr, labelset + labelset_maxlen, protocol_name, protocol_name_len); 81 | if (bufptr != NULL && bufptr < labelset + labelset_maxlen) 82 | *bufptr++ = customization_label_len; 83 | bufptr = buffer_add(bufptr, labelset + labelset_maxlen, 84 | customization_label, customization_label_len); 85 | 86 | if (bufptr != NULL && bufptr - labelset == 3 + protocol_name_len + customization_label_len) { 87 | *labelset_len = bufptr - labelset; 88 | return 0; 89 | } 90 | return -1; 91 | } 92 | 93 | 94 | int labelset_add(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen, 95 | const unsigned char* label, const unsigned char label_len) 96 | { 97 | unsigned char* bufptr; 98 | if (labelset_len == NULL) 99 | return -1; 100 | if (*labelset_len > LABELSETMAXLEN || labelset_maxlen > LABELSETMAXLEN) 101 | return -1; 102 | if (*labelset_len >= labelset_maxlen || *labelset_len + label_len + 1 > labelset_maxlen) 103 | return -1; 104 | if (*labelset_len < 3 || labelset_maxlen < 4) 105 | return -1; 106 | if (label_len > LABELMAXLEN) 107 | return -1; 108 | 109 | labelset[0]++; 110 | labelset[*labelset_len] = label_len; 111 | bufptr = labelset + *labelset_len + 1; 112 | bufptr = buffer_add(bufptr, labelset + labelset_maxlen, label, label_len); 113 | if (bufptr == NULL) 114 | return -1; 115 | if (bufptr - labelset >= labelset_maxlen) 116 | return -1; 117 | if (bufptr - labelset != *labelset_len + 1 + label_len) 118 | return -1; 119 | 120 | *labelset_len += (1 + label_len); 121 | return 0; 122 | } 123 | 124 | int labelset_validate(const unsigned char* labelset, const unsigned long labelset_len) 125 | { 126 | unsigned char num_labels = 0; 127 | unsigned char count = 0; 128 | unsigned long offset = 0; 129 | unsigned char label_len = 0; 130 | 131 | if (labelset == NULL) 132 | return -1; 133 | if (labelset_len < 3 || labelset_len > LABELSETMAXLEN) 134 | return -1; 135 | 136 | num_labels = labelset[0]; 137 | offset = 1; 138 | for (count = 0; count < num_labels; count++) { 139 | label_len = labelset[offset]; 140 | if (label_len > LABELMAXLEN) 141 | return -1; 142 | offset += 1 + label_len; 143 | if (offset > labelset_len) 144 | return -1; 145 | } 146 | if (offset != labelset_len) 147 | return -1; 148 | return 0; 149 | } 150 | 151 | int labelset_is_empty(const unsigned char* labelset, const unsigned long labelset_len) 152 | { 153 | if (labelset_len != 3) 154 | return 0; 155 | return 1; 156 | } 157 | 158 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_labelset.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEN_LABELSET_H__ 2 | #define __GEN_LABELSET_H__ 3 | 4 | extern const unsigned char B_bytes[]; 5 | 6 | unsigned char* buffer_add(unsigned char* bufptr, const unsigned char* bufend, 7 | const unsigned char* in, const unsigned long in_len); 8 | 9 | unsigned char* buffer_pad(const unsigned char* buf, unsigned char* bufptr, const unsigned char* bufend); 10 | 11 | 12 | int labelset_new(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen, 13 | const unsigned char* protocol_name, const unsigned char protocol_name_len, 14 | const unsigned char* customization_label, const unsigned char customization_label_len); 15 | 16 | int labelset_add(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen, 17 | const unsigned char* label, const unsigned char label_len); 18 | 19 | int labelset_validate(const unsigned char* labelset, const unsigned long labelset_len); 20 | 21 | int labelset_is_empty(const unsigned char* labelset, const unsigned long labelset_len); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_veddsa.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEN_VEDDSA_H__ 2 | #define __GEN_VEDDSA_H__ 3 | 4 | int generalized_veddsa_25519_sign( 5 | unsigned char* signature_out, 6 | const unsigned char* eddsa_25519_pubkey_bytes, 7 | const unsigned char* eddsa_25519_privkey_scalar, 8 | const unsigned char* msg, 9 | const unsigned long msg_len, 10 | const unsigned char* random, 11 | const unsigned char* customization_label, 12 | const unsigned long customization_label_len); 13 | 14 | int generalized_veddsa_25519_verify( 15 | unsigned char* vrf_out, 16 | const unsigned char* signature, 17 | const unsigned char* eddsa_25519_pubkey_bytes, 18 | const unsigned char* msg, 19 | const unsigned long msg_len, 20 | const unsigned char* customization_label, 21 | const unsigned long customization_label_len); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_x.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_additions.h" 3 | #include "gen_x.h" 4 | #include "gen_constants.h" 5 | #include "gen_eddsa.h" 6 | #include "gen_veddsa.h" 7 | #include "gen_crypto_additions.h" 8 | #include "zeroize.h" 9 | 10 | static int convert_25519_pubkey(unsigned char* ed_pubkey_bytes, const unsigned char* x25519_pubkey_bytes) { 11 | fe u; 12 | fe y; 13 | 14 | /* Convert the X25519 public key into an Ed25519 public key. 15 | 16 | y = (u - 1) / (u + 1) 17 | 18 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 19 | */ 20 | if (!fe_isreduced(x25519_pubkey_bytes)) 21 | return -1; 22 | fe_frombytes(u, x25519_pubkey_bytes); 23 | fe_montx_to_edy(y, u); 24 | fe_tobytes(ed_pubkey_bytes, y); 25 | return 0; 26 | } 27 | 28 | static int calculate_25519_keypair(unsigned char* K_bytes, unsigned char* k_scalar, 29 | const unsigned char* x25519_privkey_scalar) 30 | { 31 | unsigned char kneg[SCALARLEN]; 32 | ge_p3 ed_pubkey_point; 33 | unsigned char sign_bit = 0; 34 | 35 | if (SCALARLEN != 32) 36 | return -1; 37 | 38 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 39 | ge_scalarmult_base(&ed_pubkey_point, x25519_privkey_scalar); 40 | ge_p3_tobytes(K_bytes, &ed_pubkey_point); 41 | 42 | /* Force Edwards sign bit to zero */ 43 | sign_bit = (K_bytes[31] & 0x80) >> 7; 44 | memcpy(k_scalar, x25519_privkey_scalar, 32); 45 | sc_neg(kneg, k_scalar); 46 | sc_cmov(k_scalar, kneg, sign_bit); 47 | K_bytes[31] &= 0x7F; 48 | 49 | zeroize(kneg, SCALARLEN); 50 | return 0; 51 | } 52 | 53 | int generalized_xeddsa_25519_sign(unsigned char* signature_out, 54 | const unsigned char* x25519_privkey_scalar, 55 | const unsigned char* msg, const unsigned long msg_len, 56 | const unsigned char* random, 57 | const unsigned char* customization_label, 58 | const unsigned long customization_label_len) 59 | { 60 | unsigned char K_bytes[POINTLEN]; 61 | unsigned char k_scalar[SCALARLEN]; 62 | int retval = -1; 63 | 64 | if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0) 65 | return -1; 66 | 67 | retval = generalized_eddsa_25519_sign(signature_out, 68 | K_bytes, k_scalar, 69 | msg, msg_len, random, 70 | customization_label, customization_label_len); 71 | zeroize(k_scalar, SCALARLEN); 72 | return retval; 73 | } 74 | 75 | int generalized_xveddsa_25519_sign( 76 | unsigned char* signature_out, 77 | const unsigned char* x25519_privkey_scalar, 78 | const unsigned char* msg, 79 | const unsigned long msg_len, 80 | const unsigned char* random, 81 | const unsigned char* customization_label, 82 | const unsigned long customization_label_len) 83 | { 84 | unsigned char K_bytes[POINTLEN]; 85 | unsigned char k_scalar[SCALARLEN]; 86 | int retval = -1; 87 | 88 | if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0) 89 | return -1; 90 | 91 | retval = generalized_veddsa_25519_sign(signature_out, K_bytes, k_scalar, 92 | msg, msg_len, random, 93 | customization_label, customization_label_len); 94 | zeroize(k_scalar, SCALARLEN); 95 | return retval; 96 | } 97 | 98 | int generalized_xeddsa_25519_verify( 99 | const unsigned char* signature, 100 | const unsigned char* x25519_pubkey_bytes, 101 | const unsigned char* msg, 102 | const unsigned long msg_len, 103 | const unsigned char* customization_label, 104 | const unsigned long customization_label_len) 105 | { 106 | unsigned char K_bytes[POINTLEN]; 107 | 108 | if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0) 109 | return -1; 110 | 111 | return generalized_eddsa_25519_verify(signature, K_bytes, msg, msg_len, 112 | customization_label, customization_label_len); 113 | } 114 | 115 | int generalized_xveddsa_25519_verify( 116 | unsigned char* vrf_out, 117 | const unsigned char* signature, 118 | const unsigned char* x25519_pubkey_bytes, 119 | const unsigned char* msg, 120 | const unsigned long msg_len, 121 | const unsigned char* customization_label, 122 | const unsigned long customization_label_len) 123 | { 124 | unsigned char K_bytes[POINTLEN]; 125 | 126 | if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0) 127 | return -1; 128 | 129 | return generalized_veddsa_25519_verify(vrf_out, signature, K_bytes, msg, msg_len, 130 | customization_label, customization_label_len); 131 | } 132 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/gen_x.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEN_X_H 2 | #define __GEN_X_H 3 | 4 | int generalized_xeddsa_25519_sign(unsigned char* signature_out, /* 64 bytes */ 5 | const unsigned char* x25519_privkey_scalar, /* 32 bytes */ 6 | const unsigned char* msg, const unsigned long msg_len, 7 | const unsigned char* random, /* 32 bytes */ 8 | const unsigned char* customization_label, 9 | const unsigned long customization_label_len); 10 | 11 | int generalized_xeddsa_25519_verify( 12 | const unsigned char* signature, /* 64 bytes */ 13 | const unsigned char* x25519_pubkey_bytes, /* 32 bytes */ 14 | const unsigned char* msg, 15 | const unsigned long msg_len, 16 | const unsigned char* customization_label, 17 | const unsigned long customization_label_len); 18 | 19 | int generalized_xveddsa_25519_sign( 20 | unsigned char* signature_out, /* 96 bytes */ 21 | const unsigned char* x25519_privkey_scalar, /* 32 bytes */ 22 | const unsigned char* msg, 23 | const unsigned long msg_len, 24 | const unsigned char* random, /* 32 bytes */ 25 | const unsigned char* customization_label, 26 | const unsigned long customization_label_len); 27 | 28 | int generalized_xveddsa_25519_verify( 29 | unsigned char* vrf_out, /* 32 bytes */ 30 | const unsigned char* signature, /* 96 bytes */ 31 | const unsigned char* x25519_pubkey_bytes, /* 32 bytes */ 32 | const unsigned char* msg, 33 | const unsigned long msg_len, 34 | const unsigned char* customization_label, 35 | const unsigned long customization_label_len); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/point_isreduced.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fe.h" 3 | #include "crypto_additions.h" 4 | 5 | int point_isreduced(const unsigned char* p) 6 | { 7 | unsigned char strict[32]; 8 | 9 | memmove(strict, p, 32); 10 | strict[31] &= 0x7F; /* mask off sign bit */ 11 | return fe_isreduced(strict); 12 | } 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/generalized/sc_isreduced.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fe.h" 3 | #include "sc.h" 4 | #include "crypto_additions.h" 5 | #include "crypto_verify_32.h" 6 | 7 | int sc_isreduced(const unsigned char* s) 8 | { 9 | unsigned char strict[64]; 10 | 11 | memset(strict, 0, 64); 12 | memmove(strict, s, 32); 13 | sc_reduce(strict); 14 | if (crypto_verify_32(strict, s) != 0) 15 | return 0; 16 | return 1; 17 | } 18 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/keygen.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | #include "keygen.h" 3 | #include "crypto_additions.h" 4 | 5 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, 6 | const unsigned char* curve25519_privkey_in) 7 | { 8 | /* Perform a fixed-base multiplication of the Edwards base point, 9 | (which is efficient due to precalculated tables), then convert 10 | to the Curve25519 montgomery-format public key. 11 | 12 | NOTE: y=1 is converted to u=0 since fe_invert is mod-exp 13 | */ 14 | 15 | ge_p3 ed; /* Ed25519 pubkey point */ 16 | fe u; 17 | 18 | ge_scalarmult_base(&ed, curve25519_privkey_in); 19 | ge_p3_to_montx(u, &ed); 20 | fe_tobytes(curve25519_pubkey_out, u); 21 | } 22 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/keygen.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __KEYGEN_H__ 3 | #define __KEYGEN_H__ 4 | 5 | /* Sets and clears bits to make a random 32 bytes into a private key */ 6 | void sc_clamp(unsigned char* a); 7 | 8 | /* The private key should be 32 random bytes "clamped" by sc_clamp() */ 9 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ 10 | const unsigned char* curve25519_privkey_in); /* 32 bytes */ 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/open_modified.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "crypto_verify_32.h" 5 | #include "ge.h" 6 | #include "sc.h" 7 | #include "crypto_additions.h" 8 | 9 | int crypto_sign_open_modified( 10 | unsigned char *m, 11 | const unsigned char *sm,unsigned long long smlen, 12 | const unsigned char *pk 13 | ) 14 | { 15 | unsigned char pkcopy[32]; 16 | unsigned char rcopy[32]; 17 | unsigned char scopy[32]; 18 | unsigned char h[64]; 19 | unsigned char rcheck[32]; 20 | ge_p3 A; 21 | ge_p2 R; 22 | 23 | if (smlen < 64) goto badsig; 24 | if (sm[63] & 224) goto badsig; /* strict parsing of s */ 25 | if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; 26 | 27 | memmove(pkcopy,pk,32); 28 | memmove(rcopy,sm,32); 29 | memmove(scopy,sm + 32,32); 30 | 31 | memmove(m,sm,smlen); 32 | memmove(m + 32,pkcopy,32); 33 | crypto_hash_sha512(h,m,smlen); 34 | sc_reduce(h); 35 | 36 | ge_double_scalarmult_vartime(&R,h,&A,scopy); 37 | ge_tobytes(rcheck,&R); 38 | 39 | if (crypto_verify_32(rcheck,rcopy) == 0) { 40 | return 0; 41 | } 42 | 43 | badsig: 44 | return -1; 45 | } 46 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/sc_clamp.c: -------------------------------------------------------------------------------- 1 | #include "crypto_additions.h" 2 | 3 | void sc_clamp(unsigned char* a) 4 | { 5 | a[0] &= 248; 6 | a[31] &= 127; 7 | a[31] |= 64; 8 | } 9 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/sc_cmov.c: -------------------------------------------------------------------------------- 1 | #include "crypto_additions.h" 2 | 3 | /* 4 | Replace (f,g) with (g,g) if b == 1; 5 | replace (f,g) with (f,g) if b == 0. 6 | 7 | Preconditions: b in {0,1}. 8 | */ 9 | 10 | void sc_cmov(unsigned char* f, const unsigned char* g, unsigned char b) 11 | { 12 | int count=32; 13 | unsigned char x[32]; 14 | for (count=0; count < 32; count++) 15 | x[count] = f[count] ^ g[count]; 16 | b = -b; 17 | for (count=0; count < 32; count++) 18 | x[count] &= b; 19 | for (count=0; count < 32; count++) 20 | f[count] = f[count] ^ x[count]; 21 | } 22 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/sc_neg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_additions.h" 3 | #include "sc.h" 4 | 5 | /* l = order of base point = 2^252 + 27742317777372353535851937790883648493 */ 6 | 7 | /* 8 | static unsigned char l[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 9 | 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x10}; 12 | */ 13 | 14 | static unsigned char lminus1[32] = {0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 15 | 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 18 | 19 | /* b = -a (mod l) */ 20 | void sc_neg(unsigned char *b, const unsigned char *a) 21 | { 22 | unsigned char zero[32]; 23 | memset(zero, 0, 32); 24 | sc_muladd(b, lminus1, a, zero); /* b = (-1)a + 0 (mod l) */ 25 | } 26 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/sign_modified.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "ge.h" 5 | #include "sc.h" 6 | #include "zeroize.h" 7 | #include "crypto_additions.h" 8 | 9 | /* NEW: Compare to pristine crypto_sign() 10 | Uses explicit private key for nonce derivation and as scalar, 11 | instead of deriving both from a master key. 12 | */ 13 | int crypto_sign_modified( 14 | unsigned char *sm, 15 | const unsigned char *m,unsigned long long mlen, 16 | const unsigned char *sk, const unsigned char* pk, 17 | const unsigned char* random 18 | ) 19 | { 20 | unsigned char nonce[64]; 21 | unsigned char hram[64]; 22 | ge_p3 R; 23 | int count=0; 24 | 25 | memmove(sm + 64,m,mlen); 26 | memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */ 27 | 28 | /* NEW : add prefix to separate hash uses - see .h */ 29 | sm[0] = 0xFE; 30 | for (count = 1; count < 32; count++) 31 | sm[count] = 0xFF; 32 | 33 | /* NEW: add suffix of random data */ 34 | memmove(sm + mlen + 64, random, 64); 35 | 36 | crypto_hash_sha512(nonce,sm,mlen + 128); 37 | memmove(sm + 32,pk,32); 38 | 39 | sc_reduce(nonce); 40 | 41 | ge_scalarmult_base(&R,nonce); 42 | ge_p3_tobytes(sm,&R); 43 | 44 | crypto_hash_sha512(hram,sm,mlen + 64); 45 | sc_reduce(hram); 46 | sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */ 47 | 48 | /* Erase any traces of private scalar or 49 | nonce left in the stack from sc_muladd */ 50 | zeroize_stack(); 51 | zeroize(nonce, 64); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/utility.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utility.h" 4 | 5 | void print_vector(const char* name, const unsigned char* v) 6 | { 7 | int count; 8 | printf("%s = \n", name); 9 | for (count = 0; count < 32; count++) 10 | printf("%02x ", v[count]); 11 | printf("\n"); 12 | } 13 | 14 | void print_bytes(const char* name, const unsigned char* v, int numbytes) 15 | { 16 | int count; 17 | printf("%s = \n", name); 18 | for (count = 0; count < numbytes; count++) 19 | printf("%02x ", v[count]); 20 | printf("\n"); 21 | } 22 | 23 | void print_fe(const char* name, const fe in) 24 | { 25 | unsigned char bytes[32]; 26 | fe_tobytes(bytes, in); 27 | print_vector(name, bytes); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/utility.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __UTILITY_H__ 3 | #define __UTILITY_H__ 4 | 5 | #include "fe.h" 6 | 7 | void print_vector(const char* name, const unsigned char* v); 8 | void print_bytes(const char* name, const unsigned char* v, int numbytes); 9 | void print_fe(const char* name, const fe in); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/xeddsa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ge.h" 3 | #include "crypto_additions.h" 4 | #include "zeroize.h" 5 | #include "xeddsa.h" 6 | #include "crypto_verify_32.h" 7 | 8 | int xed25519_sign(unsigned char* signature_out, 9 | const unsigned char* curve25519_privkey, 10 | const unsigned char* msg, const unsigned long msg_len, 11 | const unsigned char* random) 12 | { 13 | unsigned char a[32], aneg[32]; 14 | unsigned char A[32]; 15 | ge_p3 ed_pubkey_point; 16 | unsigned char *sigbuf; /* working buffer */ 17 | unsigned char sign_bit = 0; 18 | 19 | if ((sigbuf = malloc(msg_len + 128)) == 0) { 20 | memset(signature_out, 0, 64); 21 | return -1; 22 | } 23 | 24 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 25 | ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); 26 | ge_p3_tobytes(A, &ed_pubkey_point); 27 | 28 | /* Force Edwards sign bit to zero */ 29 | sign_bit = (A[31] & 0x80) >> 7; 30 | memcpy(a, curve25519_privkey, 32); 31 | sc_neg(aneg, a); 32 | sc_cmov(a, aneg, sign_bit); 33 | A[31] &= 0x7F; 34 | 35 | /* Perform an Ed25519 signature with explicit private key */ 36 | crypto_sign_modified(sigbuf, msg, msg_len, a, A, random); 37 | memmove(signature_out, sigbuf, 64); 38 | 39 | zeroize(a, 32); 40 | zeroize(aneg, 32); 41 | free(sigbuf); 42 | return 0; 43 | } 44 | 45 | int xed25519_verify(const unsigned char* signature, 46 | const unsigned char* curve25519_pubkey, 47 | const unsigned char* msg, const unsigned long msg_len) 48 | { 49 | fe u; 50 | fe y; 51 | unsigned char ed_pubkey[32]; 52 | unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ 53 | unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ 54 | 55 | if (msg_len > MAX_MSG_LEN) { 56 | return -1; 57 | } 58 | 59 | /* Convert the Curve25519 public key into an Ed25519 public key. 60 | 61 | y = (u - 1) / (u + 1) 62 | 63 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 64 | */ 65 | if (!fe_isreduced(curve25519_pubkey)) 66 | return -1; 67 | fe_frombytes(u, curve25519_pubkey); 68 | fe_montx_to_edy(y, u); 69 | fe_tobytes(ed_pubkey, y); 70 | 71 | memmove(verifybuf, signature, 64); 72 | memmove(verifybuf+64, msg, msg_len); 73 | 74 | /* Then perform a normal Ed25519 verification, return 0 on success */ 75 | /* The below call has a strange API: */ 76 | /* verifybuf = R || S || message */ 77 | /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets 78 | replaced with pubkey for hashing */ 79 | return crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey); 80 | } 81 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/xeddsa.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __XEDDSA_H__ 3 | #define __XEDDSA_H__ 4 | 5 | /* returns 0 on success */ 6 | int xed25519_sign(unsigned char* signature_out, /* 64 bytes */ 7 | const unsigned char* curve25519_privkey, /* 32 bytes */ 8 | const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */ 9 | const unsigned char* random); /* 64 bytes */ 10 | 11 | /* returns 0 on success */ 12 | int xed25519_verify(const unsigned char* signature, /* 64 bytes */ 13 | const unsigned char* curve25519_pubkey, /* 32 bytes */ 14 | const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */ 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/zeroize.c: -------------------------------------------------------------------------------- 1 | #include "zeroize.h" 2 | 3 | void zeroize(unsigned char* b, size_t len) 4 | { 5 | size_t count = 0; 6 | volatile unsigned char *p = b; 7 | 8 | for (count = 0; count < len; count++) 9 | p[count] = 0; 10 | } 11 | 12 | void zeroize_stack() 13 | { 14 | unsigned char m[ZEROIZE_STACK_SIZE]; 15 | zeroize(m, ZEROIZE_STACK_SIZE); 16 | } 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/additions/zeroize.h: -------------------------------------------------------------------------------- 1 | #ifndef __ZEROIZE_H__ 2 | #define __ZEROIZE_H__ 3 | 4 | #include 5 | 6 | #define ZEROIZE_STACK_SIZE 1024 7 | 8 | void zeroize(unsigned char* b, size_t len); 9 | 10 | void zeroize_stack(); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/base2.h: -------------------------------------------------------------------------------- 1 | { 2 | { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, 3 | { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, 4 | { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, 5 | }, 6 | { 7 | { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, 8 | { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, 9 | { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, 10 | }, 11 | { 12 | { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, 13 | { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, 14 | { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, 15 | }, 16 | { 17 | { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, 18 | { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, 19 | { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, 20 | }, 21 | { 22 | { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, 23 | { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, 24 | { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 }, 25 | }, 26 | { 27 | { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, 28 | { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, 29 | { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 }, 30 | }, 31 | { 32 | { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, 33 | { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, 34 | { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 }, 35 | }, 36 | { 37 | { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, 38 | { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, 39 | { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, 40 | }, 41 | -------------------------------------------------------------------------------- /android/jni/ed25519/d.h: -------------------------------------------------------------------------------- 1 | -10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116 2 | -------------------------------------------------------------------------------- /android/jni/ed25519/d2.h: -------------------------------------------------------------------------------- 1 | -21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199 2 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "crypto_int32.h" 5 | 6 | typedef crypto_int32 fe[10]; 7 | 8 | /* 9 | fe means field element. 10 | Here the field is \Z/(2^255-19). 11 | An element t, entries t[0]...t[9], represents the integer 12 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 13 | Bounds on each t[i] vary depending on context. 14 | */ 15 | 16 | #define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes 17 | #define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes 18 | #define fe_copy crypto_sign_ed25519_ref10_fe_copy 19 | #define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero 20 | #define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative 21 | #define fe_0 crypto_sign_ed25519_ref10_fe_0 22 | #define fe_1 crypto_sign_ed25519_ref10_fe_1 23 | #define fe_cswap crypto_sign_ed25519_ref10_fe_cswap 24 | #define fe_cmov crypto_sign_ed25519_ref10_fe_cmov 25 | #define fe_add crypto_sign_ed25519_ref10_fe_add 26 | #define fe_sub crypto_sign_ed25519_ref10_fe_sub 27 | #define fe_neg crypto_sign_ed25519_ref10_fe_neg 28 | #define fe_mul crypto_sign_ed25519_ref10_fe_mul 29 | #define fe_sq crypto_sign_ed25519_ref10_fe_sq 30 | #define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2 31 | #define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666 32 | #define fe_invert crypto_sign_ed25519_ref10_fe_invert 33 | #define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523 34 | 35 | extern void fe_frombytes(fe,const unsigned char *); 36 | extern void fe_tobytes(unsigned char *,const fe); 37 | 38 | extern void fe_copy(fe,const fe); 39 | extern int fe_isnonzero(const fe); 40 | extern int fe_isnegative(const fe); 41 | extern void fe_0(fe); 42 | extern void fe_1(fe); 43 | extern void fe_cswap(fe,fe,unsigned int); 44 | extern void fe_cmov(fe,const fe,unsigned int); 45 | 46 | extern void fe_add(fe,const fe,const fe); 47 | extern void fe_sub(fe,const fe,const fe); 48 | extern void fe_neg(fe,const fe); 49 | extern void fe_mul(fe,const fe,const fe); 50 | extern void fe_sq(fe,const fe); 51 | extern void fe_sq2(fe,const fe); 52 | extern void fe_mul121666(fe,const fe); 53 | extern void fe_invert(fe,const fe); 54 | extern void fe_pow22523(fe,const fe); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_0.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 0 5 | */ 6 | 7 | void fe_0(fe h) 8 | { 9 | h[0] = 0; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_1.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 1 5 | */ 6 | 7 | void fe_1(fe h) 8 | { 9 | h[0] = 1; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_add.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f + g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_add(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 + g0; 38 | crypto_int32 h1 = f1 + g1; 39 | crypto_int32 h2 = f2 + g2; 40 | crypto_int32 h3 = f3 + g3; 41 | crypto_int32 h4 = f4 + g4; 42 | crypto_int32 h5 = f5 + g5; 43 | crypto_int32 h6 = f6 + g6; 44 | crypto_int32 h7 = f7 + g7; 45 | crypto_int32 h8 = f8 + g8; 46 | crypto_int32 h9 = f9 + g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_cmov.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Replace (f,g) with (g,g) if b == 1; 5 | replace (f,g) with (f,g) if b == 0. 6 | 7 | Preconditions: b in {0,1}. 8 | */ 9 | 10 | void fe_cmov(fe f,const fe g,unsigned int b) 11 | { 12 | crypto_int32 f0 = f[0]; 13 | crypto_int32 f1 = f[1]; 14 | crypto_int32 f2 = f[2]; 15 | crypto_int32 f3 = f[3]; 16 | crypto_int32 f4 = f[4]; 17 | crypto_int32 f5 = f[5]; 18 | crypto_int32 f6 = f[6]; 19 | crypto_int32 f7 = f[7]; 20 | crypto_int32 f8 = f[8]; 21 | crypto_int32 f9 = f[9]; 22 | crypto_int32 g0 = g[0]; 23 | crypto_int32 g1 = g[1]; 24 | crypto_int32 g2 = g[2]; 25 | crypto_int32 g3 = g[3]; 26 | crypto_int32 g4 = g[4]; 27 | crypto_int32 g5 = g[5]; 28 | crypto_int32 g6 = g[6]; 29 | crypto_int32 g7 = g[7]; 30 | crypto_int32 g8 = g[8]; 31 | crypto_int32 g9 = g[9]; 32 | crypto_int32 x0 = f0 ^ g0; 33 | crypto_int32 x1 = f1 ^ g1; 34 | crypto_int32 x2 = f2 ^ g2; 35 | crypto_int32 x3 = f3 ^ g3; 36 | crypto_int32 x4 = f4 ^ g4; 37 | crypto_int32 x5 = f5 ^ g5; 38 | crypto_int32 x6 = f6 ^ g6; 39 | crypto_int32 x7 = f7 ^ g7; 40 | crypto_int32 x8 = f8 ^ g8; 41 | crypto_int32 x9 = f9 ^ g9; 42 | b = -b; 43 | x0 &= b; 44 | x1 &= b; 45 | x2 &= b; 46 | x3 &= b; 47 | x4 &= b; 48 | x5 &= b; 49 | x6 &= b; 50 | x7 &= b; 51 | x8 &= b; 52 | x9 &= b; 53 | f[0] = f0 ^ x0; 54 | f[1] = f1 ^ x1; 55 | f[2] = f2 ^ x2; 56 | f[3] = f3 ^ x3; 57 | f[4] = f4 ^ x4; 58 | f[5] = f5 ^ x5; 59 | f[6] = f6 ^ x6; 60 | f[7] = f7 ^ x7; 61 | f[8] = f8 ^ x8; 62 | f[9] = f9 ^ x9; 63 | } 64 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_copy.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f 5 | */ 6 | 7 | void fe_copy(fe h,const fe f) 8 | { 9 | crypto_int32 f0 = f[0]; 10 | crypto_int32 f1 = f[1]; 11 | crypto_int32 f2 = f[2]; 12 | crypto_int32 f3 = f[3]; 13 | crypto_int32 f4 = f[4]; 14 | crypto_int32 f5 = f[5]; 15 | crypto_int32 f6 = f[6]; 16 | crypto_int32 f7 = f[7]; 17 | crypto_int32 f8 = f[8]; 18 | crypto_int32 f9 = f[9]; 19 | h[0] = f0; 20 | h[1] = f1; 21 | h[2] = f2; 22 | h[3] = f3; 23 | h[4] = f4; 24 | h[5] = f5; 25 | h[6] = f6; 26 | h[7] = f7; 27 | h[8] = f8; 28 | h[9] = f9; 29 | } 30 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "crypto_int64.h" 3 | #include "crypto_uint64.h" 4 | 5 | static crypto_uint64 load_3(const unsigned char *in) 6 | { 7 | crypto_uint64 result; 8 | result = (crypto_uint64) in[0]; 9 | result |= ((crypto_uint64) in[1]) << 8; 10 | result |= ((crypto_uint64) in[2]) << 16; 11 | return result; 12 | } 13 | 14 | static crypto_uint64 load_4(const unsigned char *in) 15 | { 16 | crypto_uint64 result; 17 | result = (crypto_uint64) in[0]; 18 | result |= ((crypto_uint64) in[1]) << 8; 19 | result |= ((crypto_uint64) in[2]) << 16; 20 | result |= ((crypto_uint64) in[3]) << 24; 21 | return result; 22 | } 23 | 24 | /* 25 | Ignores top bit of h. 26 | */ 27 | 28 | void fe_frombytes(fe h,const unsigned char *s) 29 | { 30 | crypto_int64 h0 = load_4(s); 31 | crypto_int64 h1 = load_3(s + 4) << 6; 32 | crypto_int64 h2 = load_3(s + 7) << 5; 33 | crypto_int64 h3 = load_3(s + 10) << 3; 34 | crypto_int64 h4 = load_3(s + 13) << 2; 35 | crypto_int64 h5 = load_4(s + 16); 36 | crypto_int64 h6 = load_3(s + 20) << 7; 37 | crypto_int64 h7 = load_3(s + 23) << 5; 38 | crypto_int64 h8 = load_3(s + 26) << 4; 39 | crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; 40 | crypto_int64 carry0; 41 | crypto_int64 carry1; 42 | crypto_int64 carry2; 43 | crypto_int64 carry3; 44 | crypto_int64 carry4; 45 | crypto_int64 carry5; 46 | crypto_int64 carry6; 47 | crypto_int64 carry7; 48 | crypto_int64 carry8; 49 | crypto_int64 carry9; 50 | 51 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 52 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 53 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 54 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 55 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 56 | 57 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 58 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 59 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 60 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 61 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 62 | 63 | h[0] = h0; 64 | h[1] = h1; 65 | h[2] = h2; 66 | h[3] = h3; 67 | h[4] = h4; 68 | h[5] = h5; 69 | h[6] = h6; 70 | h[7] = h7; 71 | h[8] = h8; 72 | h[9] = h9; 73 | } 74 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_invert.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_invert(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | fe t3; 9 | int i; 10 | 11 | #include "pow225521.h" 12 | 13 | return; 14 | } 15 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_isnegative.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | return 1 if f is in {1,3,5,...,q-2} 5 | return 0 if f is in {0,2,4,...,q-1} 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 9 | */ 10 | 11 | int fe_isnegative(const fe f) 12 | { 13 | unsigned char s[32]; 14 | fe_tobytes(s,f); 15 | return s[0] & 1; 16 | } 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_isnonzero.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "crypto_verify_32.h" 3 | 4 | /* 5 | return nonzero if f == 0 6 | return 0 if f != 0 7 | 8 | Preconditions: 9 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 10 | */ 11 | 12 | /* TREVOR'S COMMENT 13 | * 14 | * I think the above comment is wrong. Instead: 15 | * 16 | * return 0 if f == 0 17 | * return -1 if f != 0 18 | * 19 | * */ 20 | 21 | static const unsigned char zero[32]; 22 | 23 | int fe_isnonzero(const fe f) 24 | { 25 | unsigned char s[32]; 26 | fe_tobytes(s,f); 27 | return crypto_verify_32(s,zero); 28 | } 29 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_neg.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = -f 5 | 6 | Preconditions: 7 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 8 | 9 | Postconditions: 10 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 11 | */ 12 | 13 | void fe_neg(fe h,const fe f) 14 | { 15 | crypto_int32 f0 = f[0]; 16 | crypto_int32 f1 = f[1]; 17 | crypto_int32 f2 = f[2]; 18 | crypto_int32 f3 = f[3]; 19 | crypto_int32 f4 = f[4]; 20 | crypto_int32 f5 = f[5]; 21 | crypto_int32 f6 = f[6]; 22 | crypto_int32 f7 = f[7]; 23 | crypto_int32 f8 = f[8]; 24 | crypto_int32 f9 = f[9]; 25 | crypto_int32 h0 = -f0; 26 | crypto_int32 h1 = -f1; 27 | crypto_int32 h2 = -f2; 28 | crypto_int32 h3 = -f3; 29 | crypto_int32 h4 = -f4; 30 | crypto_int32 h5 = -f5; 31 | crypto_int32 h6 = -f6; 32 | crypto_int32 h7 = -f7; 33 | crypto_int32 h8 = -f8; 34 | crypto_int32 h9 = -f9; 35 | h[0] = h0; 36 | h[1] = h1; 37 | h[2] = h2; 38 | h[3] = h3; 39 | h[4] = h4; 40 | h[5] = h5; 41 | h[6] = h6; 42 | h[7] = h7; 43 | h[8] = h8; 44 | h[9] = h9; 45 | } 46 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_pow22523.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_pow22523(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | int i; 9 | 10 | #include "pow22523.h" 11 | 12 | return; 13 | } 14 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_sub.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f - g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_sub(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 - g0; 38 | crypto_int32 h1 = f1 - g1; 39 | crypto_int32 h2 = f2 - g2; 40 | crypto_int32 h3 = f3 - g3; 41 | crypto_int32 h4 = f4 - g4; 42 | crypto_int32 h5 = f5 - g5; 43 | crypto_int32 h6 = f6 - g6; 44 | crypto_int32 h7 = f7 - g7; 45 | crypto_int32 h8 = f8 - g8; 46 | crypto_int32 h9 = f9 - g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /android/jni/ed25519/fe_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Preconditions: 5 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 6 | 7 | Write p=2^255-19; q=floor(h/p). 8 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 9 | 10 | Proof: 11 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 12 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 13 | 14 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 15 | Then 0> 25; 53 | q = (h0 + q) >> 26; 54 | q = (h1 + q) >> 25; 55 | q = (h2 + q) >> 26; 56 | q = (h3 + q) >> 25; 57 | q = (h4 + q) >> 26; 58 | q = (h5 + q) >> 25; 59 | q = (h6 + q) >> 26; 60 | q = (h7 + q) >> 25; 61 | q = (h8 + q) >> 26; 62 | q = (h9 + q) >> 25; 63 | 64 | /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ 65 | h0 += 19 * q; 66 | /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ 67 | 68 | carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; 69 | carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; 70 | carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; 71 | carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; 72 | carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; 73 | carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; 74 | carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; 75 | carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; 76 | carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; 77 | carry9 = h9 >> 25; h9 -= carry9 << 25; 78 | /* h10 = carry9 */ 79 | 80 | /* 81 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 82 | Have h0+...+2^230 h9 between 0 and 2^255-1; 83 | evidently 2^255 h10-2^255 q = 0. 84 | Goal: Output h0+...+2^230 h9. 85 | */ 86 | 87 | s[0] = h0 >> 0; 88 | s[1] = h0 >> 8; 89 | s[2] = h0 >> 16; 90 | s[3] = (h0 >> 24) | (h1 << 2); 91 | s[4] = h1 >> 6; 92 | s[5] = h1 >> 14; 93 | s[6] = (h1 >> 22) | (h2 << 3); 94 | s[7] = h2 >> 5; 95 | s[8] = h2 >> 13; 96 | s[9] = (h2 >> 21) | (h3 << 5); 97 | s[10] = h3 >> 3; 98 | s[11] = h3 >> 11; 99 | s[12] = (h3 >> 19) | (h4 << 6); 100 | s[13] = h4 >> 2; 101 | s[14] = h4 >> 10; 102 | s[15] = h4 >> 18; 103 | s[16] = h5 >> 0; 104 | s[17] = h5 >> 8; 105 | s[18] = h5 >> 16; 106 | s[19] = (h5 >> 24) | (h6 << 1); 107 | s[20] = h6 >> 7; 108 | s[21] = h6 >> 15; 109 | s[22] = (h6 >> 23) | (h7 << 3); 110 | s[23] = h7 >> 5; 111 | s[24] = h7 >> 13; 112 | s[25] = (h7 >> 21) | (h8 << 4); 113 | s[26] = h8 >> 4; 114 | s[27] = h8 >> 12; 115 | s[28] = (h8 >> 20) | (h9 << 6); 116 | s[29] = h9 >> 2; 117 | s[30] = h9 >> 10; 118 | s[31] = h9 >> 18; 119 | } 120 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | /* 5 | ge means group element. 6 | 7 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 8 | satisfying -x^2 + y^2 = 1 + d x^2y^2 9 | where d = -121665/121666. 10 | 11 | Representations: 12 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 13 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 14 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 15 | ge_precomp (Duif): (y+x,y-x,2dxy) 16 | */ 17 | 18 | #include "fe.h" 19 | 20 | typedef struct { 21 | fe X; 22 | fe Y; 23 | fe Z; 24 | } ge_p2; 25 | 26 | typedef struct { 27 | fe X; 28 | fe Y; 29 | fe Z; 30 | fe T; 31 | } ge_p3; 32 | 33 | typedef struct { 34 | fe X; 35 | fe Y; 36 | fe Z; 37 | fe T; 38 | } ge_p1p1; 39 | 40 | typedef struct { 41 | fe yplusx; 42 | fe yminusx; 43 | fe xy2d; 44 | } ge_precomp; 45 | 46 | typedef struct { 47 | fe YplusX; 48 | fe YminusX; 49 | fe Z; 50 | fe T2d; 51 | } ge_cached; 52 | 53 | #define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime 54 | #define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes 55 | #define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes 56 | 57 | #define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0 58 | #define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0 59 | #define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0 60 | #define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2 61 | #define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached 62 | #define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2 63 | #define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3 64 | #define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl 65 | #define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl 66 | 67 | #define ge_madd crypto_sign_ed25519_ref10_ge_madd 68 | #define ge_msub crypto_sign_ed25519_ref10_ge_msub 69 | #define ge_add crypto_sign_ed25519_ref10_ge_add 70 | #define ge_sub crypto_sign_ed25519_ref10_ge_sub 71 | #define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base 72 | #define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime 73 | 74 | extern void ge_tobytes(unsigned char *,const ge_p2 *); 75 | extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); 76 | extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); 77 | 78 | extern void ge_p2_0(ge_p2 *); 79 | extern void ge_p3_0(ge_p3 *); 80 | extern void ge_precomp_0(ge_precomp *); 81 | extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *); 82 | extern void ge_p3_to_cached(ge_cached *,const ge_p3 *); 83 | extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); 84 | extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); 85 | extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); 86 | extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); 87 | 88 | extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 89 | extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 90 | extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); 91 | extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); 92 | extern void ge_scalarmult_base(ge_p3 *,const unsigned char *); 93 | extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_add.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_add.h" 11 | } 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_add.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_add */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YpX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YplusX); */ 55 | fe_mul(r->Z,r->X,q->YplusX); 56 | 57 | /* qhasm: B = YmX1*YmX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YminusX); */ 60 | fe_mul(r->Y,r->Y,q->YminusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D+C */ 88 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_add(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D-C */ 93 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 95 | fe_sub(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_double_scalarmult.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static void slide(signed char *r,const unsigned char *a) 4 | { 5 | int i; 6 | int b; 7 | int k; 8 | 9 | for (i = 0;i < 256;++i) 10 | r[i] = 1 & (a[i >> 3] >> (i & 7)); 11 | 12 | for (i = 0;i < 256;++i) 13 | if (r[i]) { 14 | for (b = 1;b <= 6 && i + b < 256;++b) { 15 | if (r[i + b]) { 16 | if (r[i] + (r[i + b] << b) <= 15) { 17 | r[i] += r[i + b] << b; r[i + b] = 0; 18 | } else if (r[i] - (r[i + b] << b) >= -15) { 19 | r[i] -= r[i + b] << b; 20 | for (k = i + b;k < 256;++k) { 21 | if (!r[k]) { 22 | r[k] = 1; 23 | break; 24 | } 25 | r[k] = 0; 26 | } 27 | } else 28 | break; 29 | } 30 | } 31 | } 32 | 33 | } 34 | 35 | static ge_precomp Bi[8] = { 36 | #include "base2.h" 37 | } ; 38 | 39 | /* 40 | r = a * A + b * B 41 | where a = a[0]+256*a[1]+...+256^31 a[31]. 42 | and b = b[0]+256*b[1]+...+256^31 b[31]. 43 | B is the Ed25519 base point (x,4/5) with x positive. 44 | */ 45 | 46 | void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b) 47 | { 48 | signed char aslide[256]; 49 | signed char bslide[256]; 50 | ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ 51 | ge_p1p1 t; 52 | ge_p3 u; 53 | ge_p3 A2; 54 | int i; 55 | 56 | slide(aslide,a); 57 | slide(bslide,b); 58 | 59 | ge_p3_to_cached(&Ai[0],A); 60 | ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); 61 | ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); 62 | ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); 63 | ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); 64 | ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); 65 | ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); 66 | ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); 67 | ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); 68 | 69 | ge_p2_0(r); 70 | 71 | for (i = 255;i >= 0;--i) { 72 | if (aslide[i] || bslide[i]) break; 73 | } 74 | 75 | for (;i >= 0;--i) { 76 | ge_p2_dbl(&t,r); 77 | 78 | if (aslide[i] > 0) { 79 | ge_p1p1_to_p3(&u,&t); 80 | ge_add(&t,&u,&Ai[aslide[i]/2]); 81 | } else if (aslide[i] < 0) { 82 | ge_p1p1_to_p3(&u,&t); 83 | ge_sub(&t,&u,&Ai[(-aslide[i])/2]); 84 | } 85 | 86 | if (bslide[i] > 0) { 87 | ge_p1p1_to_p3(&u,&t); 88 | ge_madd(&t,&u,&Bi[bslide[i]/2]); 89 | } else if (bslide[i] < 0) { 90 | ge_p1p1_to_p3(&u,&t); 91 | ge_msub(&t,&u,&Bi[(-bslide[i])/2]); 92 | } 93 | 94 | ge_p1p1_to_p2(r,&t); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static const fe d = { 4 | #include "d.h" 5 | } ; 6 | 7 | static const fe sqrtm1 = { 8 | #include "sqrtm1.h" 9 | } ; 10 | 11 | int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) 12 | { 13 | fe u; 14 | fe v; 15 | fe v3; 16 | fe vxx; 17 | fe check; 18 | 19 | fe_frombytes(h->Y,s); 20 | fe_1(h->Z); 21 | fe_sq(u,h->Y); 22 | fe_mul(v,u,d); 23 | fe_sub(u,u,h->Z); /* u = y^2-1 */ 24 | fe_add(v,v,h->Z); /* v = dy^2+1 */ 25 | 26 | fe_sq(v3,v); 27 | fe_mul(v3,v3,v); /* v3 = v^3 */ 28 | fe_sq(h->X,v3); 29 | fe_mul(h->X,h->X,v); 30 | fe_mul(h->X,h->X,u); /* x = uv^7 */ 31 | 32 | fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ 33 | fe_mul(h->X,h->X,v3); 34 | fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ 35 | 36 | fe_sq(vxx,h->X); 37 | fe_mul(vxx,vxx,v); 38 | fe_sub(check,vxx,u); /* vx^2-u */ 39 | if (fe_isnonzero(check)) { 40 | fe_add(check,vxx,u); /* vx^2+u */ 41 | if (fe_isnonzero(check)) return -1; 42 | fe_mul(h->X,h->X,sqrtm1); 43 | } 44 | 45 | if (fe_isnegative(h->X) == (s[31] >> 7)) 46 | fe_neg(h->X,h->X); 47 | 48 | fe_mul(h->T,h->X,h->Y); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_madd.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_madd.h" 11 | } 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_madd.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_madd */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ypx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yplusx); */ 51 | fe_mul(r->Z,r->X,q->yplusx); 52 | 53 | /* qhasm: B = YmX1*ymx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yminusx); */ 56 | fe_mul(r->Y,r->Y,q->yminusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D+C */ 79 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_add(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D-C */ 84 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 86 | fe_sub(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_msub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_msub.h" 11 | } 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_msub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_msub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ymx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yminusx); */ 51 | fe_mul(r->Z,r->X,q->yminusx); 52 | 53 | /* qhasm: B = YmX1*ypx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yplusx); */ 56 | fe_mul(r->Y,r->Y,q->yplusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D-C */ 79 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_sub(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D+C */ 84 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 86 | fe_add(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p1p1_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | } 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p1p1_to_p3.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | fe_mul(r->T,p->X,p->Y); 13 | } 14 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p2_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p2_0(ge_p2 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | } 9 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p2_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) 8 | { 9 | fe t0; 10 | #include "ge_p2_dbl.h" 11 | } 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p2_dbl.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_p2_dbl */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe A */ 11 | 12 | /* qhasm: fe AA */ 13 | 14 | /* qhasm: fe XX */ 15 | 16 | /* qhasm: fe YY */ 17 | 18 | /* qhasm: fe B */ 19 | 20 | /* qhasm: fe X3 */ 21 | 22 | /* qhasm: fe Y3 */ 23 | 24 | /* qhasm: fe Z3 */ 25 | 26 | /* qhasm: fe T3 */ 27 | 28 | /* qhasm: XX=X1^2 */ 29 | /* asm 1: fe_sq(>XX=fe#1,XX=r->X,X); */ 31 | fe_sq(r->X,p->X); 32 | 33 | /* qhasm: YY=Y1^2 */ 34 | /* asm 1: fe_sq(>YY=fe#3,YY=r->Z,Y); */ 36 | fe_sq(r->Z,p->Y); 37 | 38 | /* qhasm: B=2*Z1^2 */ 39 | /* asm 1: fe_sq2(>B=fe#4,B=r->T,Z); */ 41 | fe_sq2(r->T,p->Z); 42 | 43 | /* qhasm: A=X1+Y1 */ 44 | /* asm 1: fe_add(>A=fe#2,A=r->Y,X,Y); */ 46 | fe_add(r->Y,p->X,p->Y); 47 | 48 | /* qhasm: AA=A^2 */ 49 | /* asm 1: fe_sq(>AA=fe#5,AA=t0,Y); */ 51 | fe_sq(t0,r->Y); 52 | 53 | /* qhasm: Y3=YY+XX */ 54 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,X); */ 56 | fe_add(r->Y,r->Z,r->X); 57 | 58 | /* qhasm: Z3=YY-XX */ 59 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,Z,X); */ 61 | fe_sub(r->Z,r->Z,r->X); 62 | 63 | /* qhasm: X3=AA-Y3 */ 64 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Y); */ 66 | fe_sub(r->X,t0,r->Y); 67 | 68 | /* qhasm: T3=B-Z3 */ 69 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T,Z); */ 71 | fe_sub(r->T,r->T,r->Z); 72 | 73 | /* qhasm: return */ 74 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p3_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_0(ge_p3 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | fe_0(h->T); 9 | } 10 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p3_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) 8 | { 9 | ge_p2 q; 10 | ge_p3_to_p2(&q,p); 11 | ge_p2_dbl(r,&q); 12 | } 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p3_to_cached.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | static const fe d2 = { 8 | #include "d2.h" 9 | } ; 10 | 11 | extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) 12 | { 13 | fe_add(r->YplusX,p->Y,p->X); 14 | fe_sub(r->YminusX,p->Y,p->X); 15 | fe_copy(r->Z,p->Z); 16 | fe_mul(r->T2d,p->T,d2); 17 | } 18 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p3_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) 8 | { 9 | fe_copy(r->X,p->X); 10 | fe_copy(r->Y,p->Y); 11 | fe_copy(r->Z,p->Z); 12 | } 13 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_p3_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_precomp_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_precomp_0(ge_precomp *h) 4 | { 5 | fe_1(h->yplusx); 6 | fe_1(h->yminusx); 7 | fe_0(h->xy2d); 8 | } 9 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_scalarmult_base.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | #include "crypto_uint32.h" 3 | 4 | static unsigned char equal(signed char b,signed char c) 5 | { 6 | unsigned char ub = b; 7 | unsigned char uc = c; 8 | unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ 9 | crypto_uint32 y = x; /* 0: yes; 1..255: no */ 10 | y -= 1; /* 4294967295: yes; 0..254: no */ 11 | y >>= 31; /* 1: yes; 0: no */ 12 | return y; 13 | } 14 | 15 | static unsigned char negative(signed char b) 16 | { 17 | unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 18 | x >>= 63; /* 1: yes; 0: no */ 19 | return x; 20 | } 21 | 22 | static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) 23 | { 24 | fe_cmov(t->yplusx,u->yplusx,b); 25 | fe_cmov(t->yminusx,u->yminusx,b); 26 | fe_cmov(t->xy2d,u->xy2d,b); 27 | } 28 | 29 | /* base[i][j] = (j+1)*256^i*B */ 30 | static ge_precomp base[32][8] = { 31 | #include "base.h" 32 | } ; 33 | 34 | static void select(ge_precomp *t,int pos,signed char b) 35 | { 36 | ge_precomp minust; 37 | unsigned char bnegative = negative(b); 38 | unsigned char babs = b - (((-bnegative) & b) << 1); 39 | 40 | ge_precomp_0(t); 41 | cmov(t,&base[pos][0],equal(babs,1)); 42 | cmov(t,&base[pos][1],equal(babs,2)); 43 | cmov(t,&base[pos][2],equal(babs,3)); 44 | cmov(t,&base[pos][3],equal(babs,4)); 45 | cmov(t,&base[pos][4],equal(babs,5)); 46 | cmov(t,&base[pos][5],equal(babs,6)); 47 | cmov(t,&base[pos][6],equal(babs,7)); 48 | cmov(t,&base[pos][7],equal(babs,8)); 49 | fe_copy(minust.yplusx,t->yminusx); 50 | fe_copy(minust.yminusx,t->yplusx); 51 | fe_neg(minust.xy2d,t->xy2d); 52 | cmov(t,&minust,bnegative); 53 | } 54 | 55 | /* 56 | h = a * B 57 | where a = a[0]+256*a[1]+...+256^31 a[31] 58 | B is the Ed25519 base point (x,4/5) with x positive. 59 | 60 | Preconditions: 61 | a[31] <= 127 62 | */ 63 | 64 | void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) 65 | { 66 | signed char e[64]; 67 | signed char carry; 68 | ge_p1p1 r; 69 | ge_p2 s; 70 | ge_precomp t; 71 | int i; 72 | 73 | for (i = 0;i < 32;++i) { 74 | e[2 * i + 0] = (a[i] >> 0) & 15; 75 | e[2 * i + 1] = (a[i] >> 4) & 15; 76 | } 77 | /* each e[i] is between 0 and 15 */ 78 | /* e[63] is between 0 and 7 */ 79 | 80 | carry = 0; 81 | for (i = 0;i < 63;++i) { 82 | e[i] += carry; 83 | carry = e[i] + 8; 84 | carry >>= 4; 85 | e[i] -= carry << 4; 86 | } 87 | e[63] += carry; 88 | /* each e[i] is between -8 and 8 */ 89 | 90 | ge_p3_0(h); 91 | for (i = 1;i < 64;i += 2) { 92 | select(&t,i / 2,e[i]); 93 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 94 | } 95 | 96 | ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); 97 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 98 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 99 | ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); 100 | 101 | for (i = 0;i < 64;i += 2) { 102 | select(&t,i / 2,e[i]); 103 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_sub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_sub.h" 11 | } 12 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_sub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_sub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YmX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YminusX); */ 55 | fe_mul(r->Z,r->X,q->YminusX); 56 | 57 | /* qhasm: B = YmX1*YpX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YplusX); */ 60 | fe_mul(r->Y,r->Y,q->YplusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D-C */ 88 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_sub(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D+C */ 93 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 95 | fe_add(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /android/jni/ed25519/ge_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_tobytes(unsigned char *s,const ge_p2 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_int32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int32_h 2 | #define crypto_int32_h 3 | 4 | typedef int crypto_int32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_int64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int64_h 2 | #define crypto_int64_h 3 | 4 | typedef long long crypto_int64; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_sign.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_H 2 | #define crypto_sign_H 3 | 4 | #include "crypto_sign_edwards25519sha512batch.h" 5 | 6 | #define crypto_sign crypto_sign_edwards25519sha512batch 7 | #define crypto_sign_open crypto_sign_edwards25519sha512batch_open 8 | #define crypto_sign_keypair crypto_sign_edwards25519sha512batch_keypair 9 | #define crypto_sign_BYTES crypto_sign_edwards25519sha512batch_BYTES 10 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES 11 | #define crypto_sign_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_SECRETKEYBYTES 12 | #define crypto_sign_PRIMITIVE "edwards25519sha512batch" 13 | #define crypto_sign_IMPLEMENTATION crypto_sign_edwards25519sha512batch_IMPLEMENTATION 14 | #define crypto_sign_VERSION crypto_sign_edwards25519sha512batch_VERSION 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_sign_edwards25519sha512batch.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_edwards25519sha512batch_H 2 | #define crypto_sign_edwards25519sha512batch_H 3 | 4 | #define crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 64 5 | #define crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 32 6 | #define crypto_sign_edwards25519sha512batch_ref10_BYTES 64 7 | #ifdef __cplusplus 8 | #include 9 | extern std::string crypto_sign_edwards25519sha512batch_ref10(const std::string &,const std::string &); 10 | extern std::string crypto_sign_edwards25519sha512batch_ref10_open(const std::string &,const std::string &); 11 | extern std::string crypto_sign_edwards25519sha512batch_ref10_keypair(std::string *); 12 | extern "C" { 13 | #endif 14 | extern int crypto_sign_edwards25519sha512batch_ref10(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 15 | extern int crypto_sign_edwards25519sha512batch_ref10_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 16 | extern int crypto_sign_edwards25519sha512batch_ref10_keypair(unsigned char *,unsigned char *); 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #define crypto_sign_edwards25519sha512batch crypto_sign_edwards25519sha512batch_ref10 22 | #define crypto_sign_edwards25519sha512batch_open crypto_sign_edwards25519sha512batch_ref10_open 23 | #define crypto_sign_edwards25519sha512batch_keypair crypto_sign_edwards25519sha512batch_ref10_keypair 24 | #define crypto_sign_edwards25519sha512batch_BYTES crypto_sign_edwards25519sha512batch_ref10_BYTES 25 | #define crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 26 | #define crypto_sign_edwards25519sha512batch_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 27 | #define crypto_sign_edwards25519sha512batch_IMPLEMENTATION "crypto_sign/edwards25519sha512batch/ref10" 28 | #ifndef crypto_sign_edwards25519sha512batch_ref10_VERSION 29 | #define crypto_sign_edwards25519sha512batch_ref10_VERSION "-" 30 | #endif 31 | #define crypto_sign_edwards25519sha512batch_VERSION crypto_sign_edwards25519sha512batch_ref10_VERSION 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_uint32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint32_h 2 | #define crypto_uint32_h 3 | 4 | typedef unsigned int crypto_uint32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_uint64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint64_h 2 | #define crypto_uint64_h 3 | 4 | typedef unsigned long long crypto_uint64; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_includes/crypto_verify_32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_verify_32_H 2 | #define crypto_verify_32_H 3 | 4 | #define crypto_verify_32_ref_BYTES 32 5 | #ifdef __cplusplus 6 | #include 7 | extern "C" { 8 | #endif 9 | extern int crypto_verify_32_ref(const unsigned char *,const unsigned char *); 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #define crypto_verify_32 crypto_verify_32_ref 15 | #define crypto_verify_32_BYTES crypto_verify_32_ref_BYTES 16 | #define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/ref" 17 | #ifndef crypto_verify_32_ref_VERSION 18 | #define crypto_verify_32_ref_VERSION "-" 19 | #endif 20 | #define crypto_verify_32_VERSION crypto_verify_32_ref_VERSION 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /android/jni/ed25519/nacl_sha512/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | 20080913 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #include 8 | typedef uint64_t uint64; 9 | 10 | extern int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen); 11 | 12 | #define blocks crypto_hashblocks_sha512 13 | 14 | static const unsigned char iv[64] = { 15 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, 16 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, 17 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, 18 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, 19 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, 20 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, 21 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, 22 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 23 | } ; 24 | 25 | int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen) 26 | { 27 | unsigned char h[64]; 28 | unsigned char padded[256]; 29 | int i; 30 | unsigned long long bytes = inlen; 31 | 32 | for (i = 0;i < 64;++i) h[i] = iv[i]; 33 | 34 | blocks(h,in,inlen); 35 | in += inlen; 36 | inlen &= 127; 37 | in -= inlen; 38 | 39 | for (i = 0;i < inlen;++i) padded[i] = in[i]; 40 | padded[inlen] = 0x80; 41 | 42 | if (inlen < 112) { 43 | for (i = inlen + 1;i < 119;++i) padded[i] = 0; 44 | padded[119] = bytes >> 61; 45 | padded[120] = bytes >> 53; 46 | padded[121] = bytes >> 45; 47 | padded[122] = bytes >> 37; 48 | padded[123] = bytes >> 29; 49 | padded[124] = bytes >> 21; 50 | padded[125] = bytes >> 13; 51 | padded[126] = bytes >> 5; 52 | padded[127] = bytes << 3; 53 | blocks(h,padded,128); 54 | } else { 55 | for (i = inlen + 1;i < 247;++i) padded[i] = 0; 56 | padded[247] = bytes >> 61; 57 | padded[248] = bytes >> 53; 58 | padded[249] = bytes >> 45; 59 | padded[250] = bytes >> 37; 60 | padded[251] = bytes >> 29; 61 | padded[252] = bytes >> 21; 62 | padded[253] = bytes >> 13; 63 | padded[254] = bytes >> 5; 64 | padded[255] = bytes << 3; 65 | blocks(h,padded,256); 66 | } 67 | 68 | for (i = 0;i < 64;++i) out[i] = h[i]; 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /android/jni/ed25519/open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "crypto_verify_32.h" 5 | #include "ge.h" 6 | #include "sc.h" 7 | 8 | int crypto_sign_open( 9 | unsigned char *m,unsigned long long *mlen, 10 | const unsigned char *sm,unsigned long long smlen, 11 | const unsigned char *pk 12 | ) 13 | { 14 | unsigned char pkcopy[32]; 15 | unsigned char rcopy[32]; 16 | unsigned char scopy[32]; 17 | unsigned char h[64]; 18 | unsigned char rcheck[32]; 19 | ge_p3 A; 20 | ge_p2 R; 21 | 22 | if (smlen < 64) goto badsig; 23 | if (sm[63] & 224) goto badsig; 24 | if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; 25 | 26 | memmove(pkcopy,pk,32); 27 | memmove(rcopy,sm,32); 28 | memmove(scopy,sm + 32,32); 29 | 30 | memmove(m,sm,smlen); 31 | memmove(m + 32,pkcopy,32); 32 | crypto_hash_sha512(h,m,smlen); 33 | sc_reduce(h); 34 | 35 | ge_double_scalarmult_vartime(&R,h,&A,scopy); 36 | ge_tobytes(rcheck,&R); 37 | if (crypto_verify_32(rcheck,rcopy) == 0) { 38 | memmove(m,m + 64,smlen - 64); 39 | memset(m + smlen - 64,0,64); 40 | *mlen = smlen - 64; 41 | return 0; 42 | } 43 | 44 | badsig: 45 | *mlen = -1; 46 | memset(m,0,smlen); 47 | return -1; 48 | } 49 | -------------------------------------------------------------------------------- /android/jni/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | #define sc_reduce crypto_sign_ed25519_ref10_sc_reduce 10 | #define sc_muladd crypto_sign_ed25519_ref10_sc_muladd 11 | 12 | extern void sc_reduce(unsigned char *); 13 | extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /android/jni/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "ge.h" 5 | #include "sc.h" 6 | 7 | int crypto_sign( 8 | unsigned char *sm,unsigned long long *smlen, 9 | const unsigned char *m,unsigned long long mlen, 10 | const unsigned char *sk 11 | ) 12 | { 13 | unsigned char pk[32]; 14 | unsigned char az[64]; 15 | unsigned char nonce[64]; 16 | unsigned char hram[64]; 17 | ge_p3 R; 18 | 19 | memmove(pk,sk + 32,32); 20 | 21 | crypto_hash_sha512(az,sk,32); 22 | az[0] &= 248; 23 | az[31] &= 63; 24 | az[31] |= 64; 25 | 26 | *smlen = mlen + 64; 27 | memmove(sm + 64,m,mlen); 28 | memmove(sm + 32,az + 32,32); 29 | crypto_hash_sha512(nonce,sm + 32,mlen + 32); 30 | memmove(sm + 32,pk,32); 31 | 32 | sc_reduce(nonce); 33 | ge_scalarmult_base(&R,nonce); 34 | ge_p3_tobytes(sm,&R); 35 | 36 | crypto_hash_sha512(hram,sm,mlen + 64); 37 | sc_reduce(hram); 38 | sc_muladd(sm + 32,hram,az,nonce); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /android/jni/ed25519/sqrtm1.h: -------------------------------------------------------------------------------- 1 | -32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482 2 | -------------------------------------------------------------------------------- /android/jni/ed25519/tests/internal_fast_tests.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERNAL_FAST_TESTS_H__ 2 | #define __INTERNAL_FAST_TESTS_H__ 3 | 4 | /* silent = 0 : prints info+error messages to stdout, abort() on test failure 5 | * silent = 1 : returns 0 for success, anything else for failure 6 | */ 7 | 8 | int sha512_fast_test(int silent); 9 | int strict_fast_test(int silent); 10 | int elligator_fast_test(int silent); 11 | int curvesigs_fast_test(int silent); 12 | int xeddsa_fast_test(int silent); 13 | int vxeddsa_fast_test(int silent); 14 | int generalized_xeddsa_fast_test(int silent); 15 | int generalized_xveddsa_fast_test(int silent); 16 | 17 | int all_fast_tests(int silent); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /android/jni/ed25519/tests/internal_slow_tests.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERNAL_SLOW_TESTS_H__ 2 | #define __INTERNAL_SLOW_TESTS_H__ 3 | 4 | /* silent = 0 : prints info+error messages to stdout, abort() on test failure 5 | * silent = 1 : returns 0 for success, anything else for failure 6 | * iterations : hardcoded known-good values are at 10000, so run at least this many 7 | */ 8 | 9 | int curvesigs_slow_test(int silent, int iterations); 10 | int xeddsa_slow_test(int silent, int iterations); 11 | int xeddsa_to_curvesigs_slow_test(int silent, int iterations); 12 | int generalized_xveddsa_slow_test(int silent, int iterations); 13 | 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /android/libs/arm64-v8a/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/arm64-v8a/libcurve25519.so -------------------------------------------------------------------------------- /android/libs/armeabi-v7a/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/armeabi-v7a/libcurve25519.so -------------------------------------------------------------------------------- /android/libs/armeabi/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/armeabi/libcurve25519.so -------------------------------------------------------------------------------- /android/libs/mips/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/mips/libcurve25519.so -------------------------------------------------------------------------------- /android/libs/x86/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/x86/libcurve25519.so -------------------------------------------------------------------------------- /android/libs/x86_64/libcurve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/android/libs/x86_64/libcurve25519.so -------------------------------------------------------------------------------- /android/src/androidTest/java/org/whispersystems/curve25519/NativeCurve25519ProviderTest.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class NativeCurve25519ProviderTest extends Curve25519ProviderTest { 4 | @Override 5 | protected Curve25519Provider createProvider() throws NoSuchProviderException { 6 | return new NativeCurve25519Provider(); 7 | } 8 | 9 | private native boolean internalTest(); 10 | 11 | public void testInternalTest() throws Exception { 12 | assertTrue(internalTest()); 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /android/src/androidTest/java/org/whispersystems/curve25519/NativeCurve25519Test.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | 6 | public class NativeCurve25519Test extends Curve25519Test { 7 | 8 | private final byte[] PUBLIC_KEY = new byte[]{(byte) 0x21, (byte) 0xf7, (byte) 0x34, (byte) 0x5f, (byte) 0x56, (byte) 0xd9, (byte) 0x60, (byte) 0x2f, (byte) 0x15, (byte) 0x23, (byte) 0x29, (byte) 0x8f, (byte) 0x4f, (byte) 0x6f, (byte) 0xce, (byte) 0xcb, (byte) 0x14, (byte) 0xdd, (byte) 0xe2, (byte) 0xd5, (byte) 0xb9, (byte) 0xa9, (byte) 0xb4, (byte) 0x8b, (byte) 0xca, (byte) 0x82, (byte) 0x42, (byte) 0x68, (byte) 0x14, (byte) 0x92, (byte) 0xb9, (byte) 0x20}; 9 | private final byte[] PRIVATE_KEY = new byte[]{(byte) 0x38, (byte) 0x61, (byte) 0x1d, (byte) 0x25, (byte) 0x3b, (byte) 0xea, (byte) 0x85, (byte) 0xa2, (byte) 0x03, (byte) 0x80, (byte) 0x53, (byte) 0x43, (byte) 0xb7, (byte) 0x4a, (byte) 0x93, (byte) 0x6d, (byte) 0x3b, (byte) 0x13, (byte) 0xb9, (byte) 0xe3, (byte) 0x12, (byte) 0x14, (byte) 0x53, (byte) 0xe9, (byte) 0x74, (byte) 0x0b, (byte) 0x6b, (byte) 0x82, (byte) 0x7e, (byte) 0x33, (byte) 0x7e, (byte) 0x5d}; 10 | 11 | private final byte[] MESSAGE = new byte[]{(byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x75, (byte) 0x6e, (byte) 0x69, (byte) 0x71, (byte) 0x75, (byte) 0x65, (byte) 0x2e}; 12 | private final byte[] VRF = new byte[]{(byte) 0x45, (byte) 0xdc, (byte) 0x7b, (byte) 0x81, (byte) 0x6b, (byte) 0x01, (byte) 0xb3, (byte) 0x6c, (byte) 0xfa, (byte) 0x16, (byte) 0x45, (byte) 0xdc, (byte) 0xae, (byte) 0x8a, (byte) 0xc9, (byte) 0xbc, (byte) 0x8e, (byte) 0x52, (byte) 0x3c, (byte) 0xd8, (byte) 0x6d, (byte) 0x00, (byte) 0x7d, (byte) 0x19, (byte) 0x95, (byte) 0x3f, (byte) 0x03, (byte) 0xe7, (byte) 0xd5, (byte) 0x45, (byte) 0x54, (byte) 0xa0}; 13 | 14 | @Override 15 | public void testCheckProvider() throws NoSuchProviderException { 16 | assertTrue(Curve25519.getInstance(getProviderName()).isNative()); 17 | } 18 | 19 | @Override 20 | public String getProviderName() { 21 | return "native"; 22 | } 23 | 24 | public void testUniqueSignatures() throws Exception { 25 | Curve25519KeyPair keys = getInstance().generateKeyPair(); 26 | Random random = new Random(System.currentTimeMillis()); 27 | 28 | for (int i=1;i<=256;i++) { 29 | byte[] message = new byte[i]; 30 | random.nextBytes(message); 31 | 32 | byte[] signature = getInstance().calculateVrfSignature(keys.getPrivateKey(), message); 33 | byte[] vrf = getInstance().verifyVrfSignature(keys.getPublicKey(), message, signature); 34 | 35 | assertFalse(getInstance().verifySignature(keys.getPublicKey(), message, signature)); 36 | 37 | message[Math.abs(random.nextInt()) % message.length] ^= 0x01; 38 | 39 | try { 40 | getInstance().verifyVrfSignature(keys.getPublicKey(), message, signature); 41 | throw new AssertionError("Should have failed"); 42 | } catch (VrfSignatureVerificationFailedException e) { 43 | // good 44 | } 45 | } 46 | } 47 | 48 | public void testUniqueSignatureVector() throws Exception { 49 | Curve25519KeyPair keys = new Curve25519KeyPair(PUBLIC_KEY, PRIVATE_KEY); 50 | byte[] signature = getInstance().calculateVrfSignature(keys.getPrivateKey(), MESSAGE); 51 | byte[] vrf = getInstance().verifyVrfSignature(keys.getPublicKey(), MESSAGE, signature); 52 | 53 | assertTrue(Arrays.equals(vrf, VRF)); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | ext.version_number = "0.5.0" 3 | ext.group_info = "org.whispersystems" 4 | } 5 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/common/build.gradle -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/BaseJavaCurve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | import org.whispersystems.curve25519.java.Sha512; 10 | import org.whispersystems.curve25519.java.curve_sigs; 11 | import org.whispersystems.curve25519.java.scalarmult; 12 | 13 | abstract class BaseJavaCurve25519Provider implements Curve25519Provider { 14 | 15 | private final Sha512 sha512provider; 16 | private SecureRandomProvider secureRandomProvider; 17 | 18 | protected BaseJavaCurve25519Provider(Sha512 sha512provider, 19 | SecureRandomProvider secureRandomProvider) 20 | { 21 | this.sha512provider = sha512provider; 22 | this.secureRandomProvider = secureRandomProvider; 23 | } 24 | 25 | public abstract boolean isNative(); 26 | 27 | public void setRandomProvider(SecureRandomProvider secureRandomProvider) { 28 | this.secureRandomProvider = secureRandomProvider; 29 | } 30 | 31 | public byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic) { 32 | byte[] agreement = new byte[32]; 33 | scalarmult.crypto_scalarmult(agreement, ourPrivate, theirPublic); 34 | 35 | return agreement; 36 | } 37 | 38 | public byte[] generatePublicKey(byte[] privateKey) { 39 | byte[] publicKey = new byte[32]; 40 | curve_sigs.curve25519_keygen(publicKey, privateKey); 41 | 42 | return publicKey; 43 | } 44 | 45 | public byte[] generatePrivateKey() { 46 | byte[] random = getRandom(PRIVATE_KEY_LEN); 47 | return generatePrivateKey(random); 48 | } 49 | 50 | public byte[] generatePrivateKey(byte[] random) { 51 | byte[] privateKey = new byte[32]; 52 | 53 | System.arraycopy(random, 0, privateKey, 0, 32); 54 | 55 | privateKey[0] &= 248; 56 | privateKey[31] &= 127; 57 | privateKey[31] |= 64; 58 | 59 | return privateKey; 60 | } 61 | 62 | public byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message) { 63 | byte[] result = new byte[64]; 64 | 65 | if (curve_sigs.curve25519_sign(sha512provider, result, privateKey, message, message.length, random) != 0) { 66 | throw new IllegalArgumentException("Message exceeds max length!"); 67 | } 68 | 69 | return result; 70 | } 71 | 72 | public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature) { 73 | return curve_sigs.curve25519_verify(sha512provider, signature, publicKey, message, message.length) == 0; 74 | } 75 | 76 | public byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message) { 77 | throw new AssertionError("NYI"); 78 | } 79 | 80 | public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature) 81 | throws VrfSignatureVerificationFailedException 82 | { 83 | throw new AssertionError("NYI"); 84 | } 85 | 86 | public byte[] getRandom(int length) { 87 | byte[] result = new byte[length]; 88 | secureRandomProvider.nextBytes(result); 89 | return result; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/Curve25519KeyPair.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | /** 10 | * A tuple that contains a Curve25519 public and private key. 11 | * 12 | * @author Moxie Marlinspike 13 | */ 14 | public class Curve25519KeyPair { 15 | 16 | private final byte[] publicKey; 17 | private final byte[] privateKey; 18 | 19 | Curve25519KeyPair(byte[] publicKey, byte[] privateKey) { 20 | this.publicKey = publicKey; 21 | this.privateKey = privateKey; 22 | } 23 | 24 | /** 25 | * @return The Curve25519 public key. 26 | */ 27 | public byte[] getPublicKey() { 28 | return publicKey; 29 | } 30 | 31 | /** 32 | * @return The Curve25519 private key. 33 | */ 34 | public byte[] getPrivateKey() { 35 | return privateKey; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/Curve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | interface Curve25519Provider { 10 | 11 | static final int PRIVATE_KEY_LEN = 32; 12 | 13 | boolean isNative(); 14 | byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic); 15 | byte[] generatePublicKey(byte[] privateKey); 16 | byte[] generatePrivateKey(); 17 | byte[] generatePrivateKey(byte[] random); 18 | 19 | byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message); 20 | boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature); 21 | byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message); 22 | byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature) 23 | throws VrfSignatureVerificationFailedException; 24 | 25 | byte[] getRandom(int length); 26 | 27 | void setRandomProvider(SecureRandomProvider provider); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/NoSuchProviderException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | public class NoSuchProviderException extends RuntimeException { 10 | 11 | private final Throwable nested; 12 | 13 | public NoSuchProviderException(Throwable e) { 14 | this.nested = e; 15 | } 16 | 17 | public NoSuchProviderException(String type) { 18 | super(type); 19 | this.nested = null; 20 | } 21 | 22 | public Throwable getNested() { 23 | return nested; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/SecureRandomProvider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | public interface SecureRandomProvider { 10 | public void nextBytes(byte[] output); 11 | public int nextInt(int maxValue); 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/VrfSignatureVerificationFailedException.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class VrfSignatureVerificationFailedException extends Exception { 4 | 5 | public VrfSignatureVerificationFailedException() { 6 | super(); 7 | } 8 | 9 | public VrfSignatureVerificationFailedException(String message) { 10 | super(message); 11 | } 12 | 13 | public VrfSignatureVerificationFailedException(Exception exception) { 14 | super(exception); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/Arrays.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class Arrays { 4 | /** 5 | * Assigns the specified byte value to each element of the specified array 6 | * of bytes. 7 | * 8 | * @param a the array to be filled 9 | * @param val the value to be stored in all elements of the array 10 | */ 11 | public static void fill(byte[] a, byte val) { 12 | for (int i = 0, len = a.length; i < len; i++) 13 | a[i] = val; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/Sha512.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public interface Sha512 { 4 | 5 | public void calculateDigest(byte[] out, byte[] in, long length); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/crypto_verify_32.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class crypto_verify_32 { 4 | 5 | public static int crypto_verify_32(byte[] x, byte[] y) { 6 | int differentbits = 0; 7 | for (int count = 0; count < 32; count++) { 8 | differentbits |= (x[count] ^ y[count]); 9 | } 10 | return differentbits; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class curve_sigs { 4 | 5 | public static void curve25519_keygen(byte[] curve25519_pubkey_out, 6 | byte[] curve25519_privkey_in) 7 | { 8 | ge_p3 ed = new ge_p3(); /* Ed25519 pubkey point */ 9 | int[] ed_y_plus_one = new int[10]; 10 | int[] one_minus_ed_y = new int[10]; 11 | int[] inv_one_minus_ed_y = new int[10]; 12 | int[] mont_x = new int[10]; 13 | 14 | /* Perform a fixed-base multiplication of the Edwards base point, 15 | (which is efficient due to precalculated tables), then convert 16 | to the Curve25519 montgomery-format public key. In particular, 17 | convert Curve25519's "montgomery" x-coordinate into an Ed25519 18 | "edwards" y-coordinate: 19 | 20 | mont_x = (ed_y + 1) / (1 - ed_y) 21 | 22 | with projective coordinates: 23 | 24 | mont_x = (ed_y + ed_z) / (ed_z - ed_y) 25 | 26 | NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp 27 | */ 28 | 29 | ge_scalarmult_base.ge_scalarmult_base(ed, curve25519_privkey_in); 30 | fe_add.fe_add(ed_y_plus_one, ed.Y, ed.Z); 31 | fe_sub.fe_sub(one_minus_ed_y, ed.Z, ed.Y); 32 | fe_invert.fe_invert(inv_one_minus_ed_y, one_minus_ed_y); 33 | fe_mul.fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y); 34 | fe_tobytes.fe_tobytes(curve25519_pubkey_out, mont_x); 35 | } 36 | 37 | public static int curve25519_sign(Sha512 sha512provider, byte[] signature_out, 38 | byte[] curve25519_privkey, 39 | byte[] msg, int msg_len, 40 | byte[] random) 41 | { 42 | ge_p3 ed_pubkey_point = new ge_p3(); /* Ed25519 pubkey point */ 43 | byte[] ed_pubkey = new byte[32]; /* Ed25519 encoded pubkey */ 44 | byte[] sigbuf = new byte[msg_len + 128]; /* working buffer */ 45 | byte sign_bit = 0; 46 | 47 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 48 | ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); 49 | ge_p3_tobytes.ge_p3_tobytes(ed_pubkey, ed_pubkey_point); 50 | sign_bit = (byte)(ed_pubkey[31] & 0x80); 51 | 52 | /* Perform an Ed25519 signature with explicit private key */ 53 | sign_modified.crypto_sign_modified(sha512provider, sigbuf, msg, msg_len, curve25519_privkey, 54 | ed_pubkey, random); 55 | System.arraycopy(sigbuf, 0, signature_out, 0, 64); 56 | 57 | /* Encode the sign bit into signature (in unused high bit of S) */ 58 | signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ 59 | signature_out[63] |= sign_bit; 60 | return 0; 61 | } 62 | 63 | public static int curve25519_verify(Sha512 sha512provider, byte[] signature, 64 | byte[] curve25519_pubkey, 65 | byte[] msg, int msg_len) 66 | { 67 | int[] mont_x = new int[10]; 68 | int[] mont_x_minus_one = new int[10]; 69 | int[] mont_x_plus_one = new int[10]; 70 | int[] inv_mont_x_plus_one = new int[10]; 71 | int[] one = new int[10]; 72 | int[] ed_y = new int[10]; 73 | byte[] ed_pubkey = new byte[32]; 74 | long some_retval = 0; 75 | byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ 76 | byte[] verifybuf2 = new byte[msg_len + 64]; /* working buffer #2 */ 77 | 78 | /* Convert the Curve25519 public key into an Ed25519 public key. In 79 | particular, convert Curve25519's "montgomery" x-coordinate into an 80 | Ed25519 "edwards" y-coordinate: 81 | 82 | ed_y = (mont_x - 1) / (mont_x + 1) 83 | 84 | NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp 85 | 86 | Then move the sign bit into the pubkey from the signature. 87 | */ 88 | fe_frombytes.fe_frombytes(mont_x, curve25519_pubkey); 89 | fe_1.fe_1(one); 90 | fe_sub.fe_sub(mont_x_minus_one, mont_x, one); 91 | fe_add.fe_add(mont_x_plus_one, mont_x, one); 92 | fe_invert.fe_invert(inv_mont_x_plus_one, mont_x_plus_one); 93 | fe_mul.fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one); 94 | fe_tobytes.fe_tobytes(ed_pubkey, ed_y); 95 | 96 | /* Copy the sign bit, and remove it from signature */ 97 | ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ 98 | ed_pubkey[31] |= (signature[63] & 0x80); 99 | System.arraycopy(signature, 0, verifybuf, 0, 64); 100 | verifybuf[63] &= 0x7F; 101 | 102 | System.arraycopy(msg, 0, verifybuf, 64, (int)msg_len); 103 | 104 | /* Then perform a normal Ed25519 verification, return 0 on success */ 105 | /* The below call has a strange API: */ 106 | /* verifybuf = R || S || message */ 107 | /* verifybuf2 = java to next call gets a copy of verifybuf, S gets 108 | replaced with pubkey for hashing, then the whole thing gets zeroized 109 | (if bad sig), or contains a copy of msg (good sig) */ 110 | return open.crypto_sign_open(sha512provider, verifybuf2, some_retval, verifybuf, 64 + msg_len, ed_pubkey); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_0.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_0 { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = 0 9 | */ 10 | 11 | public static void fe_0(int[] h) 12 | { 13 | h[0] = 0; 14 | h[1] = 0; 15 | h[2] = 0; 16 | h[3] = 0; 17 | h[4] = 0; 18 | h[5] = 0; 19 | h[6] = 0; 20 | h[7] = 0; 21 | h[8] = 0; 22 | h[9] = 0; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_1.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_1 { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = 1 9 | */ 10 | 11 | public static void fe_1(int[] h) 12 | { 13 | h[0] = 1; 14 | h[1] = 0; 15 | h[2] = 0; 16 | h[3] = 0; 17 | h[4] = 0; 18 | h[5] = 0; 19 | h[6] = 0; 20 | h[7] = 0; 21 | h[8] = 0; 22 | h[9] = 0; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_add.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_add { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = f + g 9 | Can overlap h with f or g. 10 | 11 | Preconditions: 12 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 13 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 14 | 15 | Postconditions: 16 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 17 | */ 18 | 19 | public static void fe_add(int[] h,int[] f,int[] g) 20 | { 21 | int f0 = f[0]; 22 | int f1 = f[1]; 23 | int f2 = f[2]; 24 | int f3 = f[3]; 25 | int f4 = f[4]; 26 | int f5 = f[5]; 27 | int f6 = f[6]; 28 | int f7 = f[7]; 29 | int f8 = f[8]; 30 | int f9 = f[9]; 31 | int g0 = g[0]; 32 | int g1 = g[1]; 33 | int g2 = g[2]; 34 | int g3 = g[3]; 35 | int g4 = g[4]; 36 | int g5 = g[5]; 37 | int g6 = g[6]; 38 | int g7 = g[7]; 39 | int g8 = g[8]; 40 | int g9 = g[9]; 41 | int h0 = f0 + g0; 42 | int h1 = f1 + g1; 43 | int h2 = f2 + g2; 44 | int h3 = f3 + g3; 45 | int h4 = f4 + g4; 46 | int h5 = f5 + g5; 47 | int h6 = f6 + g6; 48 | int h7 = f7 + g7; 49 | int h8 = f8 + g8; 50 | int h9 = f9 + g9; 51 | h[0] = (int)h0; 52 | h[1] = (int)h1; 53 | h[2] = (int)h2; 54 | h[3] = (int)h3; 55 | h[4] = (int)h4; 56 | h[5] = (int)h5; 57 | h[6] = (int)h6; 58 | h[7] = (int)h7; 59 | h[8] = (int)h8; 60 | h[9] = (int)h9; 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_cmov.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_cmov { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | Replace (f,g) with (g,g) if b == 1; 9 | replace (f,g) with (f,g) if b == 0. 10 | 11 | Preconditions: b in {0,1}. 12 | */ 13 | 14 | public static void fe_cmov(int[] f,int[] g,int b) 15 | { 16 | int f0 = f[0]; 17 | int f1 = f[1]; 18 | int f2 = f[2]; 19 | int f3 = f[3]; 20 | int f4 = f[4]; 21 | int f5 = f[5]; 22 | int f6 = f[6]; 23 | int f7 = f[7]; 24 | int f8 = f[8]; 25 | int f9 = f[9]; 26 | int g0 = g[0]; 27 | int g1 = g[1]; 28 | int g2 = g[2]; 29 | int g3 = g[3]; 30 | int g4 = g[4]; 31 | int g5 = g[5]; 32 | int g6 = g[6]; 33 | int g7 = g[7]; 34 | int g8 = g[8]; 35 | int g9 = g[9]; 36 | int x0 = f0 ^ g0; 37 | int x1 = f1 ^ g1; 38 | int x2 = f2 ^ g2; 39 | int x3 = f3 ^ g3; 40 | int x4 = f4 ^ g4; 41 | int x5 = f5 ^ g5; 42 | int x6 = f6 ^ g6; 43 | int x7 = f7 ^ g7; 44 | int x8 = f8 ^ g8; 45 | int x9 = f9 ^ g9; 46 | b = -b; 47 | x0 &= b; 48 | x1 &= b; 49 | x2 &= b; 50 | x3 &= b; 51 | x4 &= b; 52 | x5 &= b; 53 | x6 &= b; 54 | x7 &= b; 55 | x8 &= b; 56 | x9 &= b; 57 | f[0] = f0 ^ x0; 58 | f[1] = f1 ^ x1; 59 | f[2] = f2 ^ x2; 60 | f[3] = f3 ^ x3; 61 | f[4] = f4 ^ x4; 62 | f[5] = f5 ^ x5; 63 | f[6] = f6 ^ x6; 64 | f[7] = f7 ^ x7; 65 | f[8] = f8 ^ x8; 66 | f[9] = f9 ^ x9; 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_copy.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_copy { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = f 9 | */ 10 | 11 | public static void fe_copy(int[] h,int[] f) 12 | { 13 | int f0 = f[0]; 14 | int f1 = f[1]; 15 | int f2 = f[2]; 16 | int f3 = f[3]; 17 | int f4 = f[4]; 18 | int f5 = f[5]; 19 | int f6 = f[6]; 20 | int f7 = f[7]; 21 | int f8 = f[8]; 22 | int f9 = f[9]; 23 | h[0] = f0; 24 | h[1] = f1; 25 | h[2] = f2; 26 | h[3] = f3; 27 | h[4] = f4; 28 | h[5] = f5; 29 | h[6] = f6; 30 | h[7] = f7; 31 | h[8] = f8; 32 | h[9] = f9; 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_cswap.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_cswap { 4 | 5 | //CONVERT #include 6 | //CONVERT #include "fe.h" 7 | 8 | /* 9 | Replace (f,g) with (g,f) if b == 1; 10 | replace (f,g) with (f,g) if b == 0. 11 | 12 | Preconditions: b in {0,1}. 13 | */ 14 | 15 | public static void fe_cswap(int[] f,int[] g,int b) 16 | { 17 | int f0 = f[0]; 18 | int f1 = f[1]; 19 | int f2 = f[2]; 20 | int f3 = f[3]; 21 | int f4 = f[4]; 22 | int f5 = f[5]; 23 | int f6 = f[6]; 24 | int f7 = f[7]; 25 | int f8 = f[8]; 26 | int f9 = f[9]; 27 | int g0 = g[0]; 28 | int g1 = g[1]; 29 | int g2 = g[2]; 30 | int g3 = g[3]; 31 | int g4 = g[4]; 32 | int g5 = g[5]; 33 | int g6 = g[6]; 34 | int g7 = g[7]; 35 | int g8 = g[8]; 36 | int g9 = g[9]; 37 | int x0 = f0 ^ g0; 38 | int x1 = f1 ^ g1; 39 | int x2 = f2 ^ g2; 40 | int x3 = f3 ^ g3; 41 | int x4 = f4 ^ g4; 42 | int x5 = f5 ^ g5; 43 | int x6 = f6 ^ g6; 44 | int x7 = f7 ^ g7; 45 | int x8 = f8 ^ g8; 46 | int x9 = f9 ^ g9; 47 | b = -b; 48 | x0 &= b; 49 | x1 &= b; 50 | x2 &= b; 51 | x3 &= b; 52 | x4 &= b; 53 | x5 &= b; 54 | x6 &= b; 55 | x7 &= b; 56 | x8 &= b; 57 | x9 &= b; 58 | f[0] = f0 ^ x0; 59 | f[1] = f1 ^ x1; 60 | f[2] = f2 ^ x2; 61 | f[3] = f3 ^ x3; 62 | f[4] = f4 ^ x4; 63 | f[5] = f5 ^ x5; 64 | f[6] = f6 ^ x6; 65 | f[7] = f7 ^ x7; 66 | f[8] = f8 ^ x8; 67 | f[9] = f9 ^ x9; 68 | g[0] = g0 ^ x0; 69 | g[1] = g1 ^ x1; 70 | g[2] = g2 ^ x2; 71 | g[3] = g3 ^ x3; 72 | g[4] = g4 ^ x4; 73 | g[5] = g5 ^ x5; 74 | g[6] = g6 ^ x6; 75 | g[7] = g7 ^ x7; 76 | g[8] = g8 ^ x8; 77 | g[9] = g9 ^ x9; 78 | } 79 | 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_frombytes.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_frombytes { 4 | 5 | //CONVERT #include "fe.h" 6 | //CONVERT #include "long.h" 7 | //CONVERT #include "long.h" 8 | 9 | public static long load_3(byte[] in, int index) 10 | { 11 | long result; 12 | result = ((long) in[index + 0]) & 0xFF; 13 | result |= (((long) in[index + 1]) << 8) & 0xFF00; 14 | result |= (((long) in[index + 2]) << 16) & 0xFF0000; 15 | return result; 16 | } 17 | 18 | public static long load_4(byte[] in, int index) 19 | { 20 | long result; 21 | result = (((long) in[index + 0]) & 0xFF); 22 | result |= ((((long) in[index + 1]) << 8) & 0xFF00); 23 | result |= ((((long) in[index + 2]) << 16) & 0xFF0000); 24 | result |= ((((long) in[index + 3]) << 24) & 0xFF000000L); 25 | return result; 26 | } 27 | 28 | /* 29 | Ignores top bit of h. 30 | */ 31 | 32 | public static void fe_frombytes(int[] h,byte[] s) 33 | { 34 | long h0 = load_4(s, 0); 35 | long h1 = load_3(s, 4) << 6; 36 | long h2 = load_3(s, 7) << 5; 37 | long h3 = load_3(s, 10) << 3; 38 | long h4 = load_3(s, 13) << 2; 39 | long h5 = load_4(s, 16); 40 | long h6 = load_3(s, 20) << 7; 41 | long h7 = load_3(s, 23) << 5; 42 | long h8 = load_3(s, 26) << 4; 43 | long h9 = (load_3(s, 29) & 8388607) << 2; 44 | long carry0; 45 | long carry1; 46 | long carry2; 47 | long carry3; 48 | long carry4; 49 | long carry5; 50 | long carry6; 51 | long carry7; 52 | long carry8; 53 | long carry9; 54 | 55 | carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 56 | carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 57 | carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 58 | carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 59 | carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 60 | 61 | carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 62 | carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 63 | carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 64 | carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 65 | carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 66 | 67 | h[0] = (int)h0; 68 | h[1] = (int)h1; 69 | h[2] = (int)h2; 70 | h[3] = (int)h3; 71 | h[4] = (int)h4; 72 | h[5] = (int)h5; 73 | h[6] = (int)h6; 74 | h[7] = (int)h7; 75 | h[8] = (int)h8; 76 | h[9] = (int)h9; 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_isnegative.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_isnegative { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | return 1 if f is in {1,3,5,...,q-2} 9 | return 0 if f is in {0,2,4,...,q-1} 10 | 11 | Preconditions: 12 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | public static int fe_isnegative(int[] f) 16 | { 17 | byte[] s = new byte[32]; 18 | fe_tobytes.fe_tobytes(s,f); 19 | return s[0] & 1; 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_isnonzero.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_isnonzero { 4 | 5 | //CONVERT #include "fe.h" 6 | //CONVERT #include "crypto_verify_32.crypto_verify_32.h" 7 | 8 | /* 9 | return 1 if f == 0 10 | return 0 if f != 0 11 | 12 | Preconditions: 13 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 14 | */ 15 | 16 | static final byte[] zero = new byte[32]; 17 | 18 | public static int fe_isnonzero(int[] f) 19 | { 20 | byte[] s = new byte[32]; 21 | fe_tobytes.fe_tobytes(s,f); 22 | return crypto_verify_32.crypto_verify_32(s,zero); 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_mul121666.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_mul121666 { 4 | 5 | //CONVERT #include "fe.h" 6 | //CONVERT #include "long.h" 7 | 8 | /* 9 | h = f * 121666 10 | Can overlap h with f. 11 | 12 | Preconditions: 13 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 14 | 15 | Postconditions: 16 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 17 | */ 18 | 19 | public static void fe_mul121666(int[] h,int[] f) 20 | { 21 | int f0 = f[0]; 22 | int f1 = f[1]; 23 | int f2 = f[2]; 24 | int f3 = f[3]; 25 | int f4 = f[4]; 26 | int f5 = f[5]; 27 | int f6 = f[6]; 28 | int f7 = f[7]; 29 | int f8 = f[8]; 30 | int f9 = f[9]; 31 | long h0 = f0 * (long) 121666; 32 | long h1 = f1 * (long) 121666; 33 | long h2 = f2 * (long) 121666; 34 | long h3 = f3 * (long) 121666; 35 | long h4 = f4 * (long) 121666; 36 | long h5 = f5 * (long) 121666; 37 | long h6 = f6 * (long) 121666; 38 | long h7 = f7 * (long) 121666; 39 | long h8 = f8 * (long) 121666; 40 | long h9 = f9 * (long) 121666; 41 | long carry0; 42 | long carry1; 43 | long carry2; 44 | long carry3; 45 | long carry4; 46 | long carry5; 47 | long carry6; 48 | long carry7; 49 | long carry8; 50 | long carry9; 51 | 52 | carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 53 | carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 54 | carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 55 | carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 56 | carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 57 | 58 | carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 59 | carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 60 | carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 61 | carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 62 | carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 63 | 64 | h[0] = (int)h0; 65 | h[1] = (int)h1; 66 | h[2] = (int)h2; 67 | h[3] = (int)h3; 68 | h[4] = (int)h4; 69 | h[5] = (int)h5; 70 | h[6] = (int)h6; 71 | h[7] = (int)h7; 72 | h[8] = (int)h8; 73 | h[9] = (int)h9; 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_neg.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_neg { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = -f 9 | 10 | Preconditions: 11 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 12 | 13 | Postconditions: 14 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 15 | */ 16 | 17 | public static void fe_neg(int[] h,int[] f) 18 | { 19 | int f0 = f[0]; 20 | int f1 = f[1]; 21 | int f2 = f[2]; 22 | int f3 = f[3]; 23 | int f4 = f[4]; 24 | int f5 = f[5]; 25 | int f6 = f[6]; 26 | int f7 = f[7]; 27 | int f8 = f[8]; 28 | int f9 = f[9]; 29 | int h0 = -f0; 30 | int h1 = -f1; 31 | int h2 = -f2; 32 | int h3 = -f3; 33 | int h4 = -f4; 34 | int h5 = -f5; 35 | int h6 = -f6; 36 | int h7 = -f7; 37 | int h8 = -f8; 38 | int h9 = -f9; 39 | h[0] = (int)h0; 40 | h[1] = (int)h1; 41 | h[2] = (int)h2; 42 | h[3] = (int)h3; 43 | h[4] = (int)h4; 44 | h[5] = (int)h5; 45 | h[6] = (int)h6; 46 | h[7] = (int)h7; 47 | h[8] = (int)h8; 48 | h[9] = (int)h9; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_sub.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_sub { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | h = f - g 9 | Can overlap h with f or g. 10 | 11 | Preconditions: 12 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 13 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 14 | 15 | Postconditions: 16 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 17 | */ 18 | 19 | public static void fe_sub(int[] h,int[] f,int[] g) 20 | { 21 | int f0 = f[0]; 22 | int f1 = f[1]; 23 | int f2 = f[2]; 24 | int f3 = f[3]; 25 | int f4 = f[4]; 26 | int f5 = f[5]; 27 | int f6 = f[6]; 28 | int f7 = f[7]; 29 | int f8 = f[8]; 30 | int f9 = f[9]; 31 | int g0 = g[0]; 32 | int g1 = g[1]; 33 | int g2 = g[2]; 34 | int g3 = g[3]; 35 | int g4 = g[4]; 36 | int g5 = g[5]; 37 | int g6 = g[6]; 38 | int g7 = g[7]; 39 | int g8 = g[8]; 40 | int g9 = g[9]; 41 | int h0 = f0 - g0; 42 | int h1 = f1 - g1; 43 | int h2 = f2 - g2; 44 | int h3 = f3 - g3; 45 | int h4 = f4 - g4; 46 | int h5 = f5 - g5; 47 | int h6 = f6 - g6; 48 | int h7 = f7 - g7; 49 | int h8 = f8 - g8; 50 | int h9 = f9 - g9; 51 | h[0] = (int)h0; 52 | h[1] = (int)h1; 53 | h[2] = (int)h2; 54 | h[3] = (int)h3; 55 | h[4] = (int)h4; 56 | h[5] = (int)h5; 57 | h[6] = (int)h6; 58 | h[7] = (int)h7; 59 | h[8] = (int)h8; 60 | h[9] = (int)h9; 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/fe_tobytes.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class fe_tobytes { 4 | 5 | //CONVERT #include "fe.h" 6 | 7 | /* 8 | Preconditions: 9 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 10 | 11 | Write p=2^255-19; q=floor(h/p). 12 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 13 | 14 | Proof: 15 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 16 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 17 | 18 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 19 | Then 0> 25; 57 | q = (h0 + q) >> 26; 58 | q = (h1 + q) >> 25; 59 | q = (h2 + q) >> 26; 60 | q = (h3 + q) >> 25; 61 | q = (h4 + q) >> 26; 62 | q = (h5 + q) >> 25; 63 | q = (h6 + q) >> 26; 64 | q = (h7 + q) >> 25; 65 | q = (h8 + q) >> 26; 66 | q = (h9 + q) >> 25; 67 | 68 | /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ 69 | h0 += 19 * q; 70 | /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ 71 | 72 | carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; 73 | carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; 74 | carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; 75 | carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; 76 | carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; 77 | carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; 78 | carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; 79 | carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; 80 | carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; 81 | carry9 = h9 >> 25; h9 -= carry9 << 25; 82 | /* h10 = carry9 */ 83 | 84 | /* 85 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 86 | Have h0+...+2^230 h9 between 0 and 2^255-1; 87 | evidently 2^255 h10-2^255 q = 0. 88 | Goal: Output h0+...+2^230 h9. 89 | */ 90 | 91 | s[0] = (byte)(h0 >> 0); 92 | s[1] = (byte)(h0 >> 8); 93 | s[2] = (byte)(h0 >> 16); 94 | s[3] = (byte)((h0 >> 24) | (h1 << 2)); 95 | s[4] = (byte)(h1 >> 6); 96 | s[5] = (byte)(h1 >> 14); 97 | s[6] = (byte)((h1 >> 22) | (h2 << 3)); 98 | s[7] = (byte)(h2 >> 5); 99 | s[8] = (byte)(h2 >> 13); 100 | s[9] = (byte)((h2 >> 21) | (h3 << 5)); 101 | s[10] = (byte)(h3 >> 3); 102 | s[11] = (byte)(h3 >> 11); 103 | s[12] = (byte)((h3 >> 19) | (h4 << 6)); 104 | s[13] = (byte)(h4 >> 2); 105 | s[14] = (byte)(h4 >> 10); 106 | s[15] = (byte)(h4 >> 18); 107 | s[16] = (byte)(h5 >> 0); 108 | s[17] = (byte)(h5 >> 8); 109 | s[18] = (byte)(h5 >> 16); 110 | s[19] = (byte)((h5 >> 24) | (h6 << 1)); 111 | s[20] = (byte)(h6 >> 7); 112 | s[21] = (byte)(h6 >> 15); 113 | s[22] = (byte)((h6 >> 23) | (h7 << 3)); 114 | s[23] = (byte)(h7 >> 5); 115 | s[24] = (byte)(h7 >> 13); 116 | s[25] = (byte)((h7 >> 21) | (h8 << 4)); 117 | s[26] = (byte)(h8 >> 4); 118 | s[27] = (byte)(h8 >> 12); 119 | s[28] = (byte)((h8 >> 20) | (h9 << 6)); 120 | s[29] = (byte)(h9 >> 2); 121 | s[30] = (byte)(h9 >> 10); 122 | s[31] = (byte)(h9 >> 18); 123 | } 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/ge_add.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class ge_add { 4 | 5 | //CONVERT #include "ge.h" 6 | 7 | /* 8 | r = p + q 9 | */ 10 | 11 | public static void ge_add(ge_p1p1 r,ge_p3 p,ge_cached q) 12 | { 13 | int[] t0 = new int[10]; 14 | //CONVERT #include "ge_add.h" 15 | 16 | /* qhasm: enter ge_add */ 17 | 18 | /* qhasm: fe X1 */ 19 | 20 | /* qhasm: fe Y1 */ 21 | 22 | /* qhasm: fe Z1 */ 23 | 24 | /* qhasm: fe Z2 */ 25 | 26 | /* qhasm: fe T1 */ 27 | 28 | /* qhasm: fe ZZ */ 29 | 30 | /* qhasm: fe YpX2 */ 31 | 32 | /* qhasm: fe YmX2 */ 33 | 34 | /* qhasm: fe T2d2 */ 35 | 36 | /* qhasm: fe X3 */ 37 | 38 | /* qhasm: fe Y3 */ 39 | 40 | /* qhasm: fe Z3 */ 41 | 42 | /* qhasm: fe T3 */ 43 | 44 | /* qhasm: fe YpX1 */ 45 | 46 | /* qhasm: fe YmX1 */ 47 | 48 | /* qhasm: fe A */ 49 | 50 | /* qhasm: fe B */ 51 | 52 | /* qhasm: fe C */ 53 | 54 | /* qhasm: fe D */ 55 | 56 | /* qhasm: YpX1 = Y1+X1 */ 57 | /* asm 1: fe_add.fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,>> 7) & 0x01)) { 52 | fe_neg.fe_neg(h.X,h.X); 53 | } 54 | 55 | fe_mul.fe_mul(h.T,h.X,h.Y); 56 | return 0; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/ge_madd.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class ge_madd { 4 | 5 | //CONVERT #include "ge.h" 6 | 7 | /* 8 | r = p + q 9 | */ 10 | 11 | public static void ge_madd(ge_p1p1 r,ge_p3 p,ge_precomp q) 12 | { 13 | int[] t0 = new int[10]; 14 | //CONVERT #include "ge_madd.h" 15 | 16 | /* qhasm: enter ge_madd */ 17 | 18 | /* qhasm: fe X1 */ 19 | 20 | /* qhasm: fe Y1 */ 21 | 22 | /* qhasm: fe Z1 */ 23 | 24 | /* qhasm: fe T1 */ 25 | 26 | /* qhasm: fe ypx2 */ 27 | 28 | /* qhasm: fe ymx2 */ 29 | 30 | /* qhasm: fe xy2d2 */ 31 | 32 | /* qhasm: fe X3 */ 33 | 34 | /* qhasm: fe Y3 */ 35 | 36 | /* qhasm: fe Z3 */ 37 | 38 | /* qhasm: fe T3 */ 39 | 40 | /* qhasm: fe YpX1 */ 41 | 42 | /* qhasm: fe YmX1 */ 43 | 44 | /* qhasm: fe A */ 45 | 46 | /* qhasm: fe B */ 47 | 48 | /* qhasm: fe C */ 49 | 50 | /* qhasm: fe D */ 51 | 52 | /* qhasm: YpX1 = Y1+X1 */ 53 | /* asm 1: fe_add.fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,XX=fe#1,XX=r.X,YY=fe#3,YY=r.Z,B=fe#4,B=r.T,A=fe#2,A=r.Y,AA=fe#5,AA=t0,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,X3=fe#1,X3=r.X,T3=fe#4,T3=r.T,>>= 31; /* 1: yes; 0: no */ 16 | return y; 17 | } 18 | 19 | static int negative(byte b) 20 | { 21 | long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 22 | x >>>= 63; /* 1: yes; 0: no */ 23 | return (int)x; 24 | } 25 | 26 | static void cmov(ge_precomp t,ge_precomp u,int b) 27 | { 28 | fe_cmov.fe_cmov(t.yplusx,u.yplusx,b); 29 | fe_cmov.fe_cmov(t.yminusx,u.yminusx,b); 30 | fe_cmov.fe_cmov(t.xy2d,u.xy2d,b); 31 | } 32 | 33 | static void select(ge_precomp t,int pos,byte b) 34 | { 35 | ge_precomp base[][] = (pos <= 7 ? ge_precomp_base_0_7.base : 36 | (pos <= 15 ? ge_precomp_base_8_15.base : 37 | (pos <= 23 ? ge_precomp_base_16_23.base : ge_precomp_base_24_31.base))); 38 | 39 | ge_precomp minust = new ge_precomp(); 40 | int bnegative = negative(b); 41 | int babs = b - (((-bnegative) & b) << 1); 42 | 43 | ge_precomp_0.ge_precomp_0(t); 44 | cmov(t,base[pos][0],equal((byte)babs,(byte)1)); 45 | cmov(t,base[pos][1],equal((byte)babs,(byte)2)); 46 | cmov(t,base[pos][2],equal((byte)babs,(byte)3)); 47 | cmov(t,base[pos][3],equal((byte)babs,(byte)4)); 48 | cmov(t,base[pos][4],equal((byte)babs,(byte)5)); 49 | cmov(t,base[pos][5],equal((byte)babs,(byte)6)); 50 | cmov(t,base[pos][6],equal((byte)babs,(byte)7)); 51 | cmov(t,base[pos][7],equal((byte)babs,(byte)8)); 52 | fe_copy.fe_copy(minust.yplusx,t.yminusx); 53 | fe_copy.fe_copy(minust.yminusx,t.yplusx); 54 | fe_neg.fe_neg(minust.xy2d,t.xy2d); 55 | cmov(t,minust,bnegative); 56 | } 57 | 58 | /* 59 | h = a * B 60 | where a = a[0]+256*a[1]+...+256^31 a[31] 61 | B is the Ed25519 base point (x,4/5) with x positive. 62 | 63 | Preconditions: 64 | a[31] <= 127 65 | */ 66 | 67 | public static void ge_scalarmult_base(ge_p3 h,byte[] a) 68 | { 69 | byte[] e = new byte[64]; 70 | byte carry; 71 | ge_p1p1 r = new ge_p1p1(); 72 | ge_p2 s = new ge_p2(); 73 | ge_precomp t = new ge_precomp(); 74 | int i; 75 | 76 | for (i = 0;i < 32;++i) { 77 | e[2 * i + 0] = (byte)((a[i] >>> 0) & 15); 78 | e[2 * i + 1] = (byte)((a[i] >>> 4) & 15); 79 | } 80 | /* each e[i] is between 0 and 15 */ 81 | /* e[63] is between 0 and 7 */ 82 | 83 | carry = 0; 84 | for (i = 0;i < 63;++i) { 85 | e[i] += carry; 86 | carry = (byte)(e[i] + 8); 87 | carry >>= 4; 88 | e[i] -= carry << 4; 89 | } 90 | e[63] += carry; 91 | /* each e[i] is between -8 and 8 */ 92 | 93 | ge_p3_0.ge_p3_0(h); 94 | for (i = 1;i < 64;i += 2) { 95 | select(t,i / 2,e[i]); 96 | ge_madd.ge_madd(r,h,t); ge_p1p1_to_p3.ge_p1p1_to_p3(h,r); 97 | } 98 | 99 | ge_p3_dbl.ge_p3_dbl(r,h); ge_p1p1_to_p2.ge_p1p1_to_p2(s,r); 100 | ge_p2_dbl.ge_p2_dbl(r,s); ge_p1p1_to_p2.ge_p1p1_to_p2(s,r); 101 | ge_p2_dbl.ge_p2_dbl(r,s); ge_p1p1_to_p2.ge_p1p1_to_p2(s,r); 102 | ge_p2_dbl.ge_p2_dbl(r,s); ge_p1p1_to_p3.ge_p1p1_to_p3(h,r); 103 | 104 | for (i = 0;i < 64;i += 2) { 105 | select(t,i / 2,e[i]); 106 | ge_madd.ge_madd(r,h,t); ge_p1p1_to_p3.ge_p1p1_to_p3(h,r); 107 | } 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/ge_sub.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class ge_sub { 4 | 5 | //CONVERT #include "ge.h" 6 | 7 | /* 8 | r = p - q 9 | */ 10 | 11 | public static void ge_sub(ge_p1p1 r,ge_p3 p,ge_cached q) 12 | { 13 | int[] t0 = new int[10]; 14 | //CONVERT #include "ge_sub.h" 15 | 16 | /* qhasm: enter ge_sub */ 17 | 18 | /* qhasm: fe X1 */ 19 | 20 | /* qhasm: fe Y1 */ 21 | 22 | /* qhasm: fe Z1 */ 23 | 24 | /* qhasm: fe Z2 */ 25 | 26 | /* qhasm: fe T1 */ 27 | 28 | /* qhasm: fe ZZ */ 29 | 30 | /* qhasm: fe YpX2 */ 31 | 32 | /* qhasm: fe YmX2 */ 33 | 34 | /* qhasm: fe T2d2 */ 35 | 36 | /* qhasm: fe X3 */ 37 | 38 | /* qhasm: fe Y3 */ 39 | 40 | /* qhasm: fe Z3 */ 41 | 42 | /* qhasm: fe T3 */ 43 | 44 | /* qhasm: fe YpX1 */ 45 | 46 | /* qhasm: fe YmX1 */ 47 | 48 | /* qhasm: fe A */ 49 | 50 | /* qhasm: fe B */ 51 | 52 | /* qhasm: fe C */ 53 | 54 | /* qhasm: fe D */ 55 | 56 | /* qhasm: YpX1 = Y1+X1 */ 57 | /* asm 1: fe_add.fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T, 6 | //CONVERT #include "crypto_sign.h" 7 | //CONVERT #include "crypto_hash_sha512.h" 8 | //CONVERT #include "crypto_verify_32.h" 9 | //CONVERT #include "ge.h" 10 | //CONVERT #include "sc.h" 11 | 12 | public static int crypto_sign_open( 13 | Sha512 sha512provider, 14 | byte[] m, long mlen, 15 | byte[] sm, long smlen, 16 | byte[] pk 17 | ) 18 | { 19 | byte[] pkcopy = new byte[32]; 20 | byte[] rcopy = new byte[32]; 21 | byte[] scopy = new byte[32]; 22 | byte[] h = new byte[64]; 23 | byte[] rcheck = new byte[32]; 24 | ge_p3 A = new ge_p3(); 25 | ge_p2 R = new ge_p2(); 26 | 27 | if (smlen < 64) return -1; 28 | if ((sm[63] & 224) != 0) return -1; 29 | if (ge_frombytes.ge_frombytes_negate_vartime(A,pk) != 0) return -1; 30 | 31 | byte[] pubkeyhash = new byte[64]; 32 | sha512provider.calculateDigest(pubkeyhash,pk,32); 33 | 34 | System.arraycopy(pk, 0, pkcopy, 0, 32); 35 | System.arraycopy(sm, 0, rcopy, 0, 32); 36 | System.arraycopy(sm, 32, scopy, 0, 32); 37 | 38 | System.arraycopy(sm, 0, m, 0, (int)smlen); 39 | System.arraycopy(pkcopy, 0, m, 32, 32); 40 | sha512provider.calculateDigest(h,m,smlen); 41 | sc_reduce.sc_reduce(h); 42 | 43 | ge_double_scalarmult.ge_double_scalarmult_vartime(R,h,A,scopy); 44 | ge_tobytes.ge_tobytes(rcheck,R); 45 | if (crypto_verify_32.crypto_verify_32(rcheck,rcopy) == 0) { 46 | System.arraycopy(m, 64, m, 0, (int)(smlen - 64)); 47 | //memset(m + smlen - 64,0,64); 48 | return 0; 49 | } 50 | 51 | //badsig: 52 | //memset(m,0,smlen); 53 | return -1; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /common/src/main/java/org/whispersystems/curve25519/java/sign_modified.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519.java; 2 | 3 | public class sign_modified { 4 | 5 | //CONVERT #include 6 | //CONVERT #include "crypto_sign.h" 7 | //CONVERT #include "crypto_hash_sha512.h" 8 | //CONVERT #include "ge.h" 9 | //CONVERT #include "sc.h" 10 | //CONVERT #include "zeroize.h" 11 | 12 | /* NEW: Compare to pristine crypto_sign() 13 | Uses explicit private key for nonce derivation and as scalar, 14 | instead of deriving both from a master key. 15 | */ 16 | static int crypto_sign_modified ( 17 | Sha512 sha512provider, 18 | byte[] sm, 19 | byte[] m, long mlen, 20 | byte[] sk, byte[] pk, 21 | byte[] random 22 | ) 23 | { 24 | byte[] nonce = new byte[64]; 25 | byte[] hram = new byte[64]; 26 | ge_p3 R = new ge_p3(); 27 | int count=0; 28 | 29 | System.arraycopy(m, 0, sm, 64, (int)mlen); 30 | System.arraycopy(sk, 0, sm, 32, 32); 31 | 32 | /* NEW : add prefix to separate hash uses - see .h */ 33 | sm[0] = (byte)0xFE; 34 | for (count = 1; count < 32; count++) 35 | sm[count] = (byte)0xFF; 36 | 37 | /* NEW: add suffix of random data */ 38 | System.arraycopy(random, 0, sm, (int)(mlen + 64), 64); 39 | 40 | sha512provider.calculateDigest(nonce,sm,mlen + 128); 41 | System.arraycopy(pk, 0, sm, 32, 32); 42 | 43 | sc_reduce.sc_reduce(nonce); 44 | ge_scalarmult_base.ge_scalarmult_base(R,nonce); 45 | ge_p3_tobytes.ge_p3_tobytes(sm,R); 46 | 47 | sha512provider.calculateDigest(hram,sm,mlen + 64); 48 | sc_reduce.sc_reduce(hram); 49 | byte[] S = new byte[32]; 50 | sc_muladd.sc_muladd(S,hram,sk,nonce); /* NEW: Use privkey directly */ 51 | System.arraycopy(S, 0, sm, 32, 32); 52 | 53 | return 0; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/signalapp/curve25519-java/70fae57d6dccff7e78a46203c534314b07dfdd98/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Oct 17 15:10:52 PDT 2016 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-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /j2me/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'maven' 3 | apply plugin: 'signing' 4 | 5 | sourceCompatibility = 1.2 6 | archivesBaseName = "curve25519-j2me" 7 | version = version_number 8 | group = group_info 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | sourceSets { 15 | main { 16 | java { 17 | srcDirs = ['src/main/java', project(':common').file('src/main/java')] 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | testCompile project(':tests') 24 | compile 'org.bouncycastle:bcprov-jdk12:130' 25 | } 26 | 27 | 28 | signing { 29 | required { has("release") && gradle.taskGraph.hasTask("uploadArchives") } 30 | sign configurations.archives 31 | } 32 | 33 | uploadArchives { 34 | configuration = configurations.archives 35 | repositories.mavenDeployer { 36 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 37 | 38 | repository(url: sonatypeRepo) { 39 | authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword) 40 | } 41 | 42 | pom.project { 43 | name 'curve25519-j2me' 44 | packaging 'jar' 45 | description 'Curve25519 library for J2ME' 46 | url 'https://github.com/WhisperSystems/curve25519-java' 47 | 48 | scm { 49 | url 'scm:git@github.com:WhisperSystems/curve25519-java.git' 50 | connection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 51 | developerConnection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 52 | } 53 | 54 | licenses { 55 | license { 56 | name 'GPLv3' 57 | url 'https://www.gnu.org/licenses/gpl-3.0.txt' 58 | distribution 'repo' 59 | } 60 | } 61 | 62 | developers { 63 | developer { 64 | name 'Trevor Perrin' 65 | name 'Moxie Marlinspike' 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | task installArchives(type: Upload) { 73 | description "Installs the artifacts to the local Maven repository." 74 | configuration = configurations['archives'] 75 | repositories { 76 | mavenDeployer { 77 | repository url: "file://${System.properties['user.home']}/.m2/repository" 78 | } 79 | } 80 | } 81 | 82 | 83 | task packageJavadoc(type: Jar, dependsOn: 'javadoc') { 84 | from javadoc.destinationDir 85 | classifier = 'javadoc' 86 | } 87 | 88 | task packageSources(type: Jar) { 89 | from sourceSets.main.allSource 90 | classifier = 'sources' 91 | } 92 | 93 | artifacts { 94 | archives(packageJavadoc) { 95 | type = 'javadoc' 96 | } 97 | 98 | archives packageSources 99 | } 100 | -------------------------------------------------------------------------------- /j2me/src/main/java/org/whispersystems/curve25519/BouncyCastleSha512Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | import org.bouncycastle.crypto.digests.SHA512Digest; 10 | import org.whispersystems.curve25519.java.Sha512; 11 | 12 | public class BouncyCastleSha512Provider implements Sha512 { 13 | //@Override 14 | public void calculateDigest(byte[] out, byte[] in, long length) { 15 | SHA512Digest digest = new SHA512Digest(); 16 | digest.update(in, 0, (int)length); 17 | digest.doFinal(out, 0); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /j2me/src/main/java/org/whispersystems/curve25519/J2meCurve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | public class J2meCurve25519Provider extends BaseJavaCurve25519Provider { 10 | 11 | protected J2meCurve25519Provider() { 12 | super(new BouncyCastleSha512Provider(), new NullSecureRandomProvider()); 13 | } 14 | 15 | // @Override 16 | public boolean isNative() { 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /j2me/src/main/java/org/whispersystems/curve25519/NullSecureRandomProvider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | public class NullSecureRandomProvider implements SecureRandomProvider { 10 | // @Override 11 | public void nextBytes(byte[] output) { 12 | throw new IllegalArgumentException("No default J2ME Secure Random provider available!"); 13 | } 14 | 15 | // @Override 16 | public int nextInt(int maxValue) { 17 | throw new IllegalArgumentException("No default J2ME Secure Random provider available!"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class FakeSecureRandomProvider implements SecureRandomProvider { 4 | public void nextBytes(byte[] output) { 5 | 6 | } 7 | 8 | public int nextInt(int maxValue) { 9 | return maxValue; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /j2me/src/test/java/org/whispersystems/curve25519/J2meCurve25519ProviderTest.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class J2meCurve25519ProviderTest extends Curve25519ProviderTest { 4 | protected Curve25519Provider createProvider() throws NoSuchProviderException { 5 | J2meCurve25519Provider provider = new J2meCurve25519Provider(); 6 | provider.setRandomProvider(new FakeSecureRandomProvider()); 7 | return provider; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /j2me/src/test/java/org/whispersystems/curve25519/J2meCurve25519Test.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class J2meCurve25519Test extends Curve25519Test { 4 | public void testCheckProvider() throws NoSuchProviderException { 5 | assertFalse(Curve25519.getInstance(getProviderName()).isNative()); 6 | } 7 | 8 | public String getProviderName() { 9 | return Curve25519.J2ME; 10 | } 11 | 12 | protected Curve25519 getInstance() throws NoSuchProviderException { 13 | return Curve25519.getInstance(Curve25519.J2ME, new FakeSecureRandomProvider()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /java/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | apply plugin: 'maven' 4 | apply plugin: 'signing' 5 | 6 | sourceCompatibility = 1.7 7 | archivesBaseName = "curve25519-java" 8 | version = version_number 9 | group = group_info 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | sourceSets { 16 | main { 17 | java { 18 | srcDirs = ['src/main/java', project(':common').file('src/main/java')] 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | testCompile project(':tests') 25 | } 26 | 27 | signing { 28 | required { has("release") && gradle.taskGraph.hasTask("uploadArchives") } 29 | sign configurations.archives 30 | } 31 | 32 | uploadArchives { 33 | configuration = configurations.archives 34 | repositories.mavenDeployer { 35 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 36 | 37 | repository(url: sonatypeRepo) { 38 | authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword) 39 | } 40 | 41 | pom.project { 42 | name 'curve25519-java' 43 | packaging 'jar' 44 | description 'Curve25519 library for Java' 45 | url 'https://github.com/WhisperSystems/curve25519-java' 46 | 47 | scm { 48 | url 'scm:git@github.com:WhisperSystems/curve25519-java.git' 49 | connection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 50 | developerConnection 'scm:git@github.com:WhisperSystems/curve25519-java.git' 51 | } 52 | 53 | licenses { 54 | license { 55 | name 'GPLv3' 56 | url 'https://www.gnu.org/licenses/gpl-3.0.txt' 57 | distribution 'repo' 58 | } 59 | } 60 | 61 | developers { 62 | developer { 63 | name 'Trevor Perrin' 64 | name 'Moxie Marlinspike' 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | task installArchives(type: Upload) { 72 | description "Installs the artifacts to the local Maven repository." 73 | configuration = configurations['archives'] 74 | repositories { 75 | mavenDeployer { 76 | repository url: "file://${System.properties['user.home']}/.m2/repository" 77 | } 78 | } 79 | } 80 | 81 | 82 | task packageJavadoc(type: Jar, dependsOn: 'javadoc') { 83 | from javadoc.destinationDir 84 | classifier = 'javadoc' 85 | } 86 | 87 | task packageSources(type: Jar) { 88 | from sourceSets.main.allSource 89 | classifier = 'sources' 90 | } 91 | 92 | artifacts { 93 | archives(packageJavadoc) { 94 | type = 'javadoc' 95 | } 96 | 97 | archives packageSources 98 | } 99 | -------------------------------------------------------------------------------- /java/src/main/java/org/whispersystems/curve25519/JCESecureRandomProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | import java.security.SecureRandom; 10 | 11 | public class JCESecureRandomProvider implements SecureRandomProvider { 12 | 13 | @Override 14 | public void nextBytes(byte[] output) { 15 | new SecureRandom().nextBytes(output); 16 | } 17 | 18 | @Override 19 | public int nextInt(int maxValue) { 20 | return new SecureRandom().nextInt(maxValue); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java/src/main/java/org/whispersystems/curve25519/JCESha512Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | import org.whispersystems.curve25519.java.Sha512; 10 | 11 | import java.security.MessageDigest; 12 | import java.security.NoSuchAlgorithmException; 13 | 14 | public class JCESha512Provider implements Sha512 { 15 | @Override 16 | public void calculateDigest(byte[] out, byte[] in, long length) { 17 | try { 18 | MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); 19 | messageDigest.update(in, 0, (int)length); 20 | byte[] digest = messageDigest.digest(); 21 | System.arraycopy(digest, 0, out, 0, digest.length); 22 | } catch (NoSuchAlgorithmException e) { 23 | throw new AssertionError(e); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /java/src/main/java/org/whispersystems/curve25519/JavaCurve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | package org.whispersystems.curve25519; 7 | 8 | import org.whispersystems.curve25519.java.Sha512; 9 | 10 | import java.security.NoSuchAlgorithmException; 11 | import java.security.SecureRandom; 12 | 13 | public class JavaCurve25519Provider extends BaseJavaCurve25519Provider { 14 | 15 | protected JavaCurve25519Provider() { 16 | super(new JCESha512Provider(), new JCESecureRandomProvider()); 17 | } 18 | 19 | @Override 20 | public boolean isNative() { 21 | return false; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /java/src/main/java/org/whispersystems/curve25519/NativeCurve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | class NativeCurve25519Provider implements Curve25519Provider { 10 | 11 | private static boolean libraryPresent = false; 12 | private static Throwable libraryFailedException = null; 13 | 14 | static { 15 | try { 16 | System.loadLibrary("curve25519"); 17 | libraryPresent = true; 18 | } catch (UnsatisfiedLinkError | SecurityException e) { 19 | libraryPresent = false; 20 | libraryFailedException = e; 21 | } 22 | } 23 | 24 | private SecureRandomProvider secureRandomProvider = new JCESecureRandomProvider(); 25 | 26 | NativeCurve25519Provider() throws NoSuchProviderException { 27 | if (!libraryPresent) throw new NoSuchProviderException(libraryFailedException); 28 | 29 | try { 30 | smokeCheck(31337); 31 | } catch (UnsatisfiedLinkError ule) { 32 | throw new NoSuchProviderException(ule); 33 | } 34 | } 35 | 36 | @Override 37 | public boolean isNative() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public byte[] generatePrivateKey() { 43 | byte[] random = getRandom(PRIVATE_KEY_LEN); 44 | return generatePrivateKey(random); 45 | } 46 | 47 | @Override 48 | public byte[] getRandom(int length) { 49 | byte[] result = new byte[length]; 50 | secureRandomProvider.nextBytes(result); 51 | 52 | return result; 53 | } 54 | 55 | @Override 56 | public void setRandomProvider(SecureRandomProvider provider) { 57 | this.secureRandomProvider = provider; 58 | } 59 | 60 | @Override 61 | public native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic); 62 | 63 | @Override 64 | public native byte[] generatePublicKey(byte[] privateKey); 65 | 66 | @Override 67 | public native byte[] generatePrivateKey(byte[] random); 68 | 69 | @Override 70 | public native byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message); 71 | 72 | @Override 73 | public native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature); 74 | 75 | @Override 76 | public native byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message); 77 | 78 | @Override 79 | public native byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature) 80 | throws VrfSignatureVerificationFailedException; 81 | 82 | private native boolean smokeCheck(int dummy); 83 | 84 | } 85 | -------------------------------------------------------------------------------- /java/src/main/java/org/whispersystems/curve25519/OpportunisticCurve25519Provider.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014-2016 Open Whisper Systems 3 | * 4 | * Licensed according to the LICENSE file in this repository. 5 | */ 6 | 7 | package org.whispersystems.curve25519; 8 | 9 | public class OpportunisticCurve25519Provider implements Curve25519Provider { 10 | 11 | private Curve25519Provider delegate; 12 | 13 | OpportunisticCurve25519Provider() { 14 | try { 15 | delegate = new NativeCurve25519Provider(); 16 | } catch (NoSuchProviderException e) { 17 | delegate = new JavaCurve25519Provider(); 18 | } 19 | } 20 | 21 | @Override 22 | public boolean isNative() { 23 | return delegate.isNative(); 24 | } 25 | 26 | @Override 27 | public byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic) { 28 | return delegate.calculateAgreement(ourPrivate, theirPublic); 29 | } 30 | 31 | @Override 32 | public byte[] generatePublicKey(byte[] privateKey) { 33 | return delegate.generatePublicKey(privateKey); 34 | } 35 | 36 | @Override 37 | public byte[] generatePrivateKey() { 38 | return delegate.generatePrivateKey(); 39 | } 40 | 41 | @Override 42 | public byte[] generatePrivateKey(byte[] random) { 43 | return delegate.generatePrivateKey(random); 44 | } 45 | 46 | @Override 47 | public byte[] getRandom(int length) { 48 | return delegate.getRandom(length); 49 | } 50 | 51 | @Override 52 | public void setRandomProvider(SecureRandomProvider provider) { 53 | delegate.setRandomProvider(provider); 54 | } 55 | 56 | @Override 57 | public byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message) { 58 | return delegate.calculateSignature(random, privateKey, message); 59 | } 60 | 61 | @Override 62 | public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature) { 63 | return delegate.verifySignature(publicKey, message, signature); 64 | } 65 | 66 | @Override 67 | public byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message) { 68 | return delegate.calculateVrfSignature(random, privateKey, message); 69 | } 70 | 71 | @Override 72 | public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature) 73 | throws VrfSignatureVerificationFailedException 74 | { 75 | return delegate.verifyVrfSignature(publicKey, message, signature); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /java/src/test/java/org/whispersystems/curve25519/JavaCurve25519ProviderTest.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class JavaCurve25519ProviderTest extends Curve25519ProviderTest { 4 | @Override 5 | protected Curve25519Provider createProvider() { 6 | return new JavaCurve25519Provider(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /java/src/test/java/org/whispersystems/curve25519/JavaCurve25519Test.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | public class JavaCurve25519Test extends Curve25519Test { 4 | @Override 5 | public void testCheckProvider() throws NoSuchProviderException { 6 | assertFalse(Curve25519.getInstance(getProviderName()).isNative()); 7 | } 8 | 9 | @Override 10 | public String getProviderName() { 11 | return Curve25519.JAVA; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':java', ':android', ':j2me', ':common', ':tests' 2 | -------------------------------------------------------------------------------- /tests/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | sourceCompatibility = 1.7 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | compile project(':java') 11 | compile 'junit:junit:3.8.2' 12 | compile 'org.easytesting:fest-assert:1.4' 13 | } 14 | 15 | test { 16 | testLogging { 17 | events 'passed' 18 | showStandardStreams = true 19 | } 20 | 21 | include 'org/whispersystems/**' 22 | } 23 | -------------------------------------------------------------------------------- /tests/src/main/java/org/whispersystems/curve25519/Curve25519ProviderTest.java: -------------------------------------------------------------------------------- 1 | package org.whispersystems.curve25519; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import static org.fest.assertions.Assertions.assertThat; 6 | 7 | public abstract class Curve25519ProviderTest extends TestCase { 8 | 9 | protected abstract Curve25519Provider createProvider() throws NoSuchProviderException; 10 | 11 | public void testKeyGen() throws NoSuchProviderException { 12 | Curve25519Provider provider = createProvider(); 13 | 14 | byte[] in = new byte[32]; 15 | byte[] out = null; 16 | 17 | in[0] = 123; 18 | 19 | for (int count=0; count < 1000; count++) { 20 | out = provider.generatePublicKey(in); 21 | System.arraycopy(out, 0, in, 0, 32); 22 | } 23 | 24 | byte[] result2 = new byte[]{(byte)0xa2, (byte)0x3c, (byte)0x84, (byte)0x09, (byte)0xf2, 25 | (byte)0x93, (byte)0xb4, (byte)0x42, (byte)0x6a, (byte)0xf5, 26 | (byte)0xe5, (byte)0xe7, (byte)0xca, (byte)0xee, (byte)0x22, 27 | (byte)0xa0, (byte)0x01, (byte)0xc7, (byte)0x9a, (byte)0xca, 28 | (byte)0x1a, (byte)0xf2, (byte)0xea, (byte)0xcb, (byte)0x4d, 29 | (byte)0xdd, (byte)0xfa, (byte)0x05, (byte)0xf8, (byte)0xbc, 30 | (byte)0x7f, (byte)0x37}; 31 | 32 | assertThat(out).isEqualTo(result2); 33 | } 34 | 35 | public void testEcDh() throws NoSuchProviderException { 36 | Curve25519Provider provider = createProvider(); 37 | 38 | byte[] p = new byte[32]; 39 | byte[] q = null; 40 | byte[] n = new byte[32]; 41 | 42 | p[0] = 100; 43 | n[0] = 100; 44 | 45 | n = provider.generatePrivateKey(n); 46 | 47 | for (int count=0; count < 1000; count++) { 48 | q = provider.calculateAgreement(n, p); 49 | System.arraycopy(q, 0, p, 0, 32); 50 | q = provider.calculateAgreement(n, p); 51 | System.arraycopy(q, 0, n, 0, 32); 52 | n = provider.generatePrivateKey(n); 53 | } 54 | 55 | byte[] result = new byte[]{(byte)0xce, (byte)0xb4, (byte)0x4e, (byte)0xd6, (byte)0x4a, 56 | (byte)0xd4, (byte)0xc2, (byte)0xb5, (byte)0x43, (byte)0x9d, 57 | (byte)0x25, (byte)0xde, (byte)0xb1, (byte)0x10, (byte)0xa8, 58 | (byte)0xd7, (byte)0x2e, (byte)0xb3, (byte)0xe3, (byte)0x8e, 59 | (byte)0xf4, (byte)0x8a, (byte)0x42, (byte)0x73, (byte)0xb1, 60 | (byte)0x1b, (byte)0x4b, (byte)0x13, (byte)0x8d, (byte)0x17, 61 | (byte)0xf9, (byte)0x34}; 62 | 63 | assertThat(q).isEqualTo(result); 64 | } 65 | 66 | // FIXME: There's no actual vector here. If verifySignature is broken and always returns true, 67 | // this test will pass. 68 | public void testSignVerify() throws NoSuchProviderException { 69 | Curve25519Provider provider = createProvider(); 70 | 71 | byte[] msg = new byte[100]; 72 | byte[] sig_out = new byte[64]; 73 | byte[] privkey = new byte[32]; 74 | byte[] pubkey = new byte[32]; 75 | byte[] random = new byte[64]; 76 | 77 | privkey[0] = 123; 78 | 79 | for (int count=0; count < 1000; count++) { 80 | privkey = provider.generatePrivateKey(privkey); 81 | pubkey = provider.generatePublicKey (privkey); 82 | sig_out = provider.calculateSignature(random, privkey, msg); 83 | 84 | assertTrue(provider.verifySignature(pubkey, msg, sig_out)); 85 | 86 | System.arraycopy(sig_out, 0, privkey, 0, 32); 87 | } 88 | } 89 | } 90 | --------------------------------------------------------------------------------