Skip to content

Commit

Permalink
Add ed25519
Browse files Browse the repository at this point in the history
  • Loading branch information
moxie0 committed Oct 20, 2014
1 parent 79020cd commit 2ed8d33
Show file tree
Hide file tree
Showing 81 changed files with 7,997 additions and 5 deletions.
18 changes: 14 additions & 4 deletions libaxolotl/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := libcurve25519
LOCAL_SRC_FILES := curve25519-donna-jni.c
LOCAL_MODULE := libcurve25519-ref10
LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) ed25519/sha512/sha2big.c
LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/sha512 ed25519

LOCAL_STATIC_LIBRARIES := libcurve25519-donna
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := libcurve25519
LOCAL_SRC_FILES := curve25519-jni.c
LOCAL_C_INCLUDES := ed25519/additions

LOCAL_STATIC_LIBRARIES := libcurve25519-donna libcurve25519-ref10

include $(BUILD_SHARED_LIBRARY)

include $(BUILD_SHARED_LIBRARY)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2013 Open Whisper Systems
* Copyright (C) 2013-2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -20,6 +20,7 @@

#include <jni.h>
#include "curve25519-donna.h"
#include "curve_sigs.h"

JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePrivateKey
(JNIEnv *env, jclass clazz, jbyteArray random, jboolean ephemeral)
Expand Down Expand Up @@ -73,3 +74,38 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_c

return sharedKey;
}

JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray message)
{
jbyteArray signature = (*env)->NewByteArray(env, 64);
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 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);

curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength);

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

return signature;
}

JNIEXPORT jboolean JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_verifySignature
(JNIEnv *env, jclass clazz, 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 = (curve25519_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;
}
44 changes: 44 additions & 0 deletions libaxolotl/jni/ed25519/additions/compare.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <string.h>
#include "compare.h"

/* Const-time comparison from SUPERCOP, but here it's only used for
signature verification, so doesn't need to be const-time. But
copied the nacl version anyways. */
int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y)
{
unsigned int differentbits = 0;
#define F(i) differentbits |= x[i] ^ y[i];
F(0)
F(1)
F(2)
F(3)
F(4)
F(5)
F(6)
F(7)
F(8)
F(9)
F(10)
F(11)
F(12)
F(13)
F(14)
F(15)
F(16)
F(17)
F(18)
F(19)
F(20)
F(21)
F(22)
F(23)
F(24)
F(25)
F(26)
F(27)
F(28)
F(29)
F(30)
F(31)
return (1 & ((differentbits - 1) >> 8)) - 1;
}
6 changes: 6 additions & 0 deletions libaxolotl/jni/ed25519/additions/compare.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef __COMPARE_H__
#define __COMPARE_H__

int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2);

#endif
97 changes: 97 additions & 0 deletions libaxolotl/jni/ed25519/additions/curve_sigs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <string.h>
#include "ge.h"
#include "curve_sigs.h"
#include "crypto_sign.h"

void curve25519_keygen(unsigned char* curve25519_pubkey_out,
unsigned char* curve25519_privkey_in)
{
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
unsigned char ed_pubkey[32]; /* privkey followed by pubkey */
fe ed_y, one, 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) / (1 - ed_y)
*/

ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey_in);
ge_p3_tobytes(ed_pubkey, &ed_pubkey_point);
ed_pubkey[31] = ed_pubkey[31] & 0x7F; /* Mask off sign bit */
fe_frombytes(ed_y, ed_pubkey);

fe_1(one);
fe_add(ed_y_plus_one, ed_y, one);
fe_sub(one_minus_ed_y, one, 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);
}

void curve25519_sign(unsigned char* signature_out,
unsigned char* curve25519_privkey,
unsigned char* msg, unsigned long msg_len)
{
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
unsigned char ed_keypair[64]; /* privkey followed by pubkey */
unsigned char sigbuf[msg_len + 64]; /* working buffer */
unsigned long long sigbuf_out_len = 0;
unsigned char sign_bit = 0;

/* Convert the Curve25519 privkey to an Ed25519 keypair */
memmove(ed_keypair, curve25519_privkey, 32);
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(ed_keypair + 32, &ed_pubkey_point);
sign_bit = ed_keypair[63] & 0x80;

/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, &sigbuf_out_len, msg, msg_len, ed_keypair);
memmove(signature_out, sigbuf, 64);

/* Encode the sign bit into signature (in unused high bit of S) */
signature_out[63] |= sign_bit;
}

int curve25519_verify(unsigned char* signature,
unsigned char* curve25519_pubkey,
unsigned char* msg, unsigned long msg_len)
{
fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
fe one;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
unsigned char verifybuf[msg_len + 64]; /* working buffer */
unsigned char verifybuf2[msg_len + 64]; /* working buffer #2 */

/* Convert the Curve25519 public key into an Ed25519 public key. In
particular, convert Curve25519's "montgomery" x-coordinate into an
Ed25519 "edwards" y-coordinate:
ed_y = (mont_x - 1) / (mont_x + 1)
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_tobytes(ed_pubkey, ed_y);

/* Copy the sign bit, and remove it from signature */
ed_pubkey[31] |= (signature[63] & 0x80);
signature[63] &= 0x7F;

memmove(verifybuf, signature, 64);
memmove(verifybuf+64, msg, msg_len);

/* Then perform a normal Ed25519 verification, return 0 on success */
return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
}
25 changes: 25 additions & 0 deletions libaxolotl/jni/ed25519/additions/curve_sigs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

#ifndef __CURVE_SIGS_H__
#define __CURVE_SIGS_H__

void curve25519_keygen(unsigned char* curve25519_pubkey_out,
unsigned char* curve25519_privkey_in);

void curve25519_sign(unsigned char* signature_out,
unsigned char* curve25519_privkey,
unsigned char* msg, unsigned long msg_len);

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

/* helper function - modified version of crypto_sign() to use
explicit private key */
int crypto_sign_modified(
unsigned char *sm,unsigned long long *smlen,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk
);

#endif
13 changes: 13 additions & 0 deletions libaxolotl/jni/ed25519/additions/sha512.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "sha512.h"
#include "sph_sha2.h"

int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input,
unsigned long long len)
{
sph_sha512_context ctx;
sph_sha512_init(&ctx);
sph_sha512(&ctx, input, len);
sph_sha512_close(&ctx, output);
return 0;
}

10 changes: 10 additions & 0 deletions libaxolotl/jni/ed25519/additions/sha512.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef __SHA512_H__
#define __SHA512_H__

#include "sha512.h"
#include "sph_sha2.h"

int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input,
unsigned long long len);

#endif
40 changes: 40 additions & 0 deletions libaxolotl/jni/ed25519/additions/sign_modified.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <string.h>
#include "crypto_sign.h"
#include "crypto_hash_sha512.h"
#include "ge.h"
#include "sc.h"

/* NEW: Compare to pristine crypto_sign()
Uses explicit private key for nonce derivation and as scalar,
instead of deriving both from a master key.
*/
int crypto_sign_modified(
unsigned char *sm,unsigned long long *smlen,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk
)
{
unsigned char pk[32];
unsigned char az[64];
unsigned char nonce[64];
unsigned char hram[64];
ge_p3 R;

memmove(pk,sk + 32,32);

*smlen = mlen + 64;
memmove(sm + 64,m,mlen);
memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */
crypto_hash_sha512(nonce,sm + 32,mlen + 32);
memmove(sm + 32,pk,32);

sc_reduce(nonce);
ge_scalarmult_base(&R,nonce);
ge_p3_tobytes(sm,&R);

crypto_hash_sha512(hram,sm,mlen + 64);
sc_reduce(hram);
sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */

return 0;
}
4 changes: 4 additions & 0 deletions libaxolotl/jni/ed25519/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define CRYPTO_SECRETKEYBYTES 64
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 64
#define CRYPTO_DETERMINISTIC 1

0 comments on commit 2ed8d33

Please sign in to comment.