Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Commit

Permalink
Add VUF support
Browse files Browse the repository at this point in the history
// FREEBIE
  • Loading branch information
moxie0 committed Aug 11, 2016
1 parent 4566552 commit b9f2ac4
Show file tree
Hide file tree
Showing 36 changed files with 1,581 additions and 178 deletions.
43 changes: 42 additions & 1 deletion android/jni/curve25519-jni.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <jni.h>
#include "curve25519-donna.h"
#include "curve_sigs.h"
#include "xdsa.h"
#include "uxdsa.h"

JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_generatePrivateKey
(JNIEnv *env, jobject obj, jbyteArray random)
Expand Down Expand Up @@ -70,7 +72,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);

int result = curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
int result = xdsa_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);

(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
Expand Down Expand Up @@ -98,6 +100,45 @@ JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Pr
return result;
}

JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_calculateUniqueSignature
(JNIEnv *env, jobject obj, jbyteArray random, jbyteArray privateKey, jbyteArray message)
{
jbyteArray signature = (*env)->NewByteArray(env, 96);
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* randomBytes = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);

int result = uxdsa_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);

(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);

if (result == 0) return signature;
else (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/AssertionError"), "Signature failed!");
}

JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_verifyUniqueSignature
(JNIEnv *env, jobject obj, jbyteArray publicKey, jbyteArray message, jbyteArray signature)
{
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);

jboolean result = (uxdsa_verify(signatureBytes, publicKeyBytes, messageBytes, messageLength) == 0);

(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);

return result;
}


JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_smokeCheck
(JNIEnv *env, jobject obj, jint dummy)
{
Expand Down
59 changes: 59 additions & 0 deletions android/jni/ed25519/additions/crypto_additions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

#ifndef __CRYPTO_ADDITIONS__
#define __CRYPTO_ADDITIONS__

#include "crypto_uint32.h"
#include "fe.h"
#include "ge.h"

#define MAX_MSG_LEN 256

/* aneg = -a */
void sc_neg(unsigned char *aneg, const unsigned char *a);

void fe_montx_to_edy(fe edy, const fe montx);
void ge_p3_to_montx(fe montx, const ge_p3 *ed);

void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A);

void elligator(fe out, const fe in);
void hash_to_point(ge_p3* out, const unsigned char* in, const unsigned long in_len);
void calculate_Bu(ge_p3* Bu,
unsigned char* buf,
const unsigned char* msg, const unsigned long msg_len);
void calculate_Bu_and_U(ge_p3* Bu,
unsigned char* U,
unsigned char* buf,
const unsigned char* a,
const unsigned char* msg, const unsigned long msg_len);

int crypto_sign_modified(
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk, /* Curve/Ed25519 private key */
const unsigned char *pk, /* Ed25519 public key */
const unsigned char *random /* 64 bytes random to hash into nonce */
);

int crypto_sign_open_modified(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk
);

int crypto_usign_modified(
unsigned char *sm,
const unsigned char *M,unsigned long Mlen,
const unsigned char *a,
const unsigned char *A,
const unsigned char *random,
const ge_p3 *Bu,
const unsigned char *U);

int crypto_usign_open_modified(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk, ge_p3* Bu);


#endif
48 changes: 7 additions & 41 deletions android/jni/ed25519/additions/curve_sigs.c
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
#include <string.h>
#include <stdlib.h>
#include "ge.h"
#include "curve_sigs.h"
#include "crypto_sign.h"

void curve25519_keygen(unsigned char* curve25519_pubkey_out,
const unsigned char* curve25519_privkey_in)
{
ge_p3 ed; /* Ed25519 pubkey point */
fe ed_y, ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y;
fe mont_x;

/* Perform a fixed-base multiplication of the Edwards base point,
(which is efficient due to precalculated tables), then convert
to the Curve25519 montgomery-format public key. In particular,
convert Curve25519's "montgomery" x-coordinate into an Ed25519
"edwards" y-coordinate:
mont_x = (ed_y + 1) / (1 - ed_y)
with projective coordinates:
mont_x = (ed_y + ed_z) / (ed_z - ed_y)
NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp
*/

ge_scalarmult_base(&ed, curve25519_privkey_in);
fe_add(ed_y_plus_one, ed.Y, ed.Z);
fe_sub(one_minus_ed_y, ed.Z, ed.Y);
fe_invert(inv_one_minus_ed_y, one_minus_ed_y);
fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y);
fe_tobytes(curve25519_pubkey_out, mont_x);
}
#include "crypto_additions.h"

int curve25519_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
Expand Down Expand Up @@ -71,8 +41,7 @@ int curve25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
fe one;
fe mont_x;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
Expand All @@ -81,15 +50,16 @@ int curve25519_verify(const unsigned char* signature,
int result;

if ((verifybuf = malloc(msg_len + 64)) == 0) {
result = -1;
goto err;
result = -1;
goto err;
}

if ((verifybuf2 = malloc(msg_len + 64)) == 0) {
result = -1;
goto err;
}


/* Convert the Curve25519 public key into an Ed25519 public key. In
particular, convert Curve25519's "montgomery" x-coordinate into an
Ed25519 "edwards" y-coordinate:
Expand All @@ -101,11 +71,7 @@ int curve25519_verify(const unsigned char* signature,
Then move the sign bit into the pubkey from the signature.
*/
fe_frombytes(mont_x, curve25519_pubkey);
fe_1(one);
fe_sub(mont_x_minus_one, mont_x, one);
fe_add(mont_x_plus_one, mont_x, one);
fe_invert(inv_mont_x_plus_one, mont_x_plus_one);
fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one);
fe_montx_to_edy(ed_y, mont_x);
fe_tobytes(ed_pubkey, ed_y);

/* Copy the sign bit, and remove it from signature */
Expand All @@ -122,7 +88,7 @@ int curve25519_verify(const unsigned char* signature,
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing, then the whole thing gets zeroized
(if bad sig), or contains a copy of msg (good sig) */
result = crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
result = crypto_sign_open_modified(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);

err:

Expand Down
35 changes: 2 additions & 33 deletions android/jni/ed25519/additions/curve_sigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,16 @@
#ifndef __CURVE_SIGS_H__
#define __CURVE_SIGS_H__

void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */
const unsigned char* curve25519_privkey_in); /* 32 bytes */

/* returns 0 on success */
int curve25519_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */
const unsigned char* random); /* 64 bytes */

/* returns 0 on success */
int curve25519_verify(const unsigned char* signature, /* 64 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len);

/* helper function - modified version of crypto_sign() to use
explicit private key. In particular:
sk : private key
pk : public key
msg : message
prefix : 0xFE || [0xFF]*31
random : 64 bytes random
q : main subgroup order
The prefix is chosen to distinguish the two SHA512 uses below, since
prefix is an invalid encoding for R (it would encode a "field element"
of 2^255 - 2). 0xFF*32 is set aside for use in ECDH protocols, which
is why the first byte here ix 0xFE.
const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */

sig_nonce = SHA512(prefix || sk || msg || random) % q
R = g^sig_nonce
M = SHA512(R || pk || m)
S = sig_nonce + (m * sk)
signature = (R || S)
*/
int crypto_sign_modified(
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk, /* Curve/Ed25519 private key */
const unsigned char *pk, /* Ed25519 public key */
const unsigned char *random /* 64 bytes random to hash into nonce */
);

#endif
Loading

0 comments on commit b9f2ac4

Please sign in to comment.