├── .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 |
--------------------------------------------------------------------------------