mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Update to latest ref10-extract ed25519
This commit is contained in:
parent
5ea3b3038e
commit
1eb3884b7a
@ -76,17 +76,19 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_c
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature
|
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature
|
||||||
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray message)
|
(JNIEnv *env, jclass clazz, jbyteArray random, jbyteArray privateKey, jbyteArray message)
|
||||||
{
|
{
|
||||||
jbyteArray signature = (*env)->NewByteArray(env, 64);
|
jbyteArray signature = (*env)->NewByteArray(env, 64);
|
||||||
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
|
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* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
|
||||||
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
|
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
|
||||||
jsize messageLength = (*env)->GetArrayLength(env, message);
|
jsize messageLength = (*env)->GetArrayLength(env, message);
|
||||||
|
|
||||||
curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength);
|
curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
|
||||||
|
|
||||||
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
|
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
|
||||||
|
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
|
||||||
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
|
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
|
||||||
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
|
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
|
||||||
|
|
||||||
|
@ -4,11 +4,10 @@
|
|||||||
#include "crypto_sign.h"
|
#include "crypto_sign.h"
|
||||||
|
|
||||||
void curve25519_keygen(unsigned char* curve25519_pubkey_out,
|
void curve25519_keygen(unsigned char* curve25519_pubkey_out,
|
||||||
unsigned char* curve25519_privkey_in)
|
const unsigned char* curve25519_privkey_in)
|
||||||
{
|
{
|
||||||
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
|
ge_p3 ed; /* Ed25519 pubkey point */
|
||||||
unsigned char ed_pubkey[32]; /* privkey followed by pubkey */
|
fe ed_y, ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y;
|
||||||
fe ed_y, one, ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y;
|
|
||||||
fe mont_x;
|
fe mont_x;
|
||||||
|
|
||||||
/* Perform a fixed-base multiplication of the Edwards base point,
|
/* Perform a fixed-base multiplication of the Edwards base point,
|
||||||
@ -17,49 +16,49 @@ void curve25519_keygen(unsigned char* curve25519_pubkey_out,
|
|||||||
convert Curve25519's "montgomery" x-coordinate into an Ed25519
|
convert Curve25519's "montgomery" x-coordinate into an Ed25519
|
||||||
"edwards" y-coordinate:
|
"edwards" y-coordinate:
|
||||||
|
|
||||||
mont_x = (ed_y +1 1) / (1 - ed_y)
|
mont_x = (ed_y + 1) / (1 - ed_y)
|
||||||
|
|
||||||
|
with projective coordinates:
|
||||||
|
|
||||||
|
mont_x = (ed_y + ed_z) / (ed_z - ed_y)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey_in);
|
ge_scalarmult_base(&ed, curve25519_privkey_in);
|
||||||
ge_p3_tobytes(ed_pubkey, &ed_pubkey_point);
|
fe_add(ed_y_plus_one, ed.Y, ed.Z);
|
||||||
ed_pubkey[31] = ed_pubkey[31] & 0x7F; /* Mask off sign bit */
|
fe_sub(one_minus_ed_y, ed.Z, ed.Y);
|
||||||
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_invert(inv_one_minus_ed_y, one_minus_ed_y);
|
||||||
fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y);
|
fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y);
|
||||||
fe_tobytes(curve25519_pubkey_out, mont_x);
|
fe_tobytes(curve25519_pubkey_out, mont_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void curve25519_sign(unsigned char* signature_out,
|
void curve25519_sign(unsigned char* signature_out,
|
||||||
unsigned char* curve25519_privkey,
|
const unsigned char* curve25519_privkey,
|
||||||
unsigned char* msg, unsigned long msg_len)
|
const unsigned char* msg, const unsigned long msg_len,
|
||||||
|
const unsigned char* random)
|
||||||
{
|
{
|
||||||
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
|
ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */
|
||||||
unsigned char ed_keypair[64]; /* privkey followed by pubkey */
|
unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */
|
||||||
unsigned char sigbuf[msg_len + 64]; /* working buffer */
|
unsigned char sigbuf[msg_len + 64]; /* working buffer */
|
||||||
unsigned long long sigbuf_out_len = 0;
|
unsigned long long sigbuf_out_len = 0;
|
||||||
unsigned char sign_bit = 0;
|
unsigned char sign_bit = 0;
|
||||||
|
|
||||||
/* Convert the Curve25519 privkey to an Ed25519 keypair */
|
/* Convert the Curve25519 privkey to an Ed25519 public key */
|
||||||
memmove(ed_keypair, curve25519_privkey, 32);
|
|
||||||
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
|
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
|
||||||
ge_p3_tobytes(ed_keypair + 32, &ed_pubkey_point);
|
ge_p3_tobytes(ed_pubkey, &ed_pubkey_point);
|
||||||
sign_bit = ed_keypair[63] & 0x80;
|
sign_bit = ed_pubkey[31] & 0x80;
|
||||||
|
|
||||||
/* Perform an Ed25519 signature with explicit private key */
|
/* Perform an Ed25519 signature with explicit private key */
|
||||||
crypto_sign_modified(sigbuf, &sigbuf_out_len, msg, msg_len, ed_keypair);
|
crypto_sign_modified(sigbuf, &sigbuf_out_len, msg, msg_len, curve25519_privkey,
|
||||||
|
ed_pubkey, random);
|
||||||
memmove(signature_out, sigbuf, 64);
|
memmove(signature_out, sigbuf, 64);
|
||||||
|
|
||||||
/* Encode the sign bit into signature (in unused high bit of S) */
|
/* Encode the sign bit into signature (in unused high bit of S) */
|
||||||
signature_out[63] |= sign_bit;
|
signature_out[63] |= sign_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
int curve25519_verify(unsigned char* signature,
|
int curve25519_verify(const unsigned char* signature,
|
||||||
unsigned char* curve25519_pubkey,
|
const unsigned char* curve25519_pubkey,
|
||||||
unsigned char* msg, unsigned long msg_len)
|
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 mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one;
|
||||||
fe one;
|
fe one;
|
||||||
@ -87,11 +86,15 @@ int curve25519_verify(unsigned char* signature,
|
|||||||
|
|
||||||
/* Copy the sign bit, and remove it from signature */
|
/* Copy the sign bit, and remove it from signature */
|
||||||
ed_pubkey[31] |= (signature[63] & 0x80);
|
ed_pubkey[31] |= (signature[63] & 0x80);
|
||||||
signature[63] &= 0x7F;
|
|
||||||
|
|
||||||
memmove(verifybuf, signature, 64);
|
memmove(verifybuf, signature, 64);
|
||||||
|
verifybuf[63] &= 0x7F;
|
||||||
|
|
||||||
memmove(verifybuf+64, msg, msg_len);
|
memmove(verifybuf+64, msg, msg_len);
|
||||||
|
|
||||||
/* Then perform a normal Ed25519 verification, return 0 on success */
|
/* Then perform a normal Ed25519 verification, return 0 on success */
|
||||||
|
/* The below call has a strange API: */
|
||||||
|
/* verifybuf = R || S || message */
|
||||||
|
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
|
||||||
|
replaced with pubkey for hashing, then the whole thing gets zeroized */
|
||||||
return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
|
return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,45 @@
|
|||||||
#ifndef __CURVE_SIGS_H__
|
#ifndef __CURVE_SIGS_H__
|
||||||
#define __CURVE_SIGS_H__
|
#define __CURVE_SIGS_H__
|
||||||
|
|
||||||
void curve25519_keygen(unsigned char* curve25519_pubkey_out,
|
void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */
|
||||||
unsigned char* curve25519_privkey_in);
|
const unsigned char* curve25519_privkey_in); /* 32 bytes */
|
||||||
|
|
||||||
void curve25519_sign(unsigned char* signature_out,
|
void curve25519_sign(unsigned char* signature_out, /* 64 bytes */
|
||||||
unsigned char* curve25519_privkey,
|
const unsigned char* curve25519_privkey, /* 32 bytes */
|
||||||
unsigned char* msg, unsigned long msg_len);
|
const unsigned char* msg, const unsigned long msg_len,
|
||||||
|
const unsigned char* random); /* 64 bytes */
|
||||||
|
|
||||||
/* returns 0 on success */
|
/* returns 0 on success */
|
||||||
int curve25519_verify(unsigned char* signature,
|
int curve25519_verify(const unsigned char* signature, /* 64 bytes */
|
||||||
unsigned char* curve25519_pubkey,
|
const unsigned char* curve25519_pubkey, /* 32 bytes */
|
||||||
unsigned char* msg, unsigned long msg_len);
|
const unsigned char* msg, const unsigned long msg_len);
|
||||||
|
|
||||||
/* helper function - modified version of crypto_sign() to use
|
/* helper function - modified version of crypto_sign() to use
|
||||||
explicit private key */
|
explicit private key. In particular:
|
||||||
|
|
||||||
|
sk : private key
|
||||||
|
pk : public key
|
||||||
|
m : message
|
||||||
|
prefix : 0xFE || [0xFF]*31
|
||||||
|
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.
|
||||||
|
|
||||||
|
sig_nonce = (random XOR SHA512(prefix || sk || m)) % q
|
||||||
|
R = g^sig_nonce
|
||||||
|
M = SHA512(R || pk || m)
|
||||||
|
S = sig_nonce + (m * sk)
|
||||||
|
signature = (R || S)
|
||||||
|
*/
|
||||||
int crypto_sign_modified(
|
int crypto_sign_modified(
|
||||||
unsigned char *sm,unsigned long long *smlen,
|
unsigned char *sm,unsigned long long *smlen,
|
||||||
const unsigned char *m,unsigned long long mlen,
|
const unsigned char *m,unsigned long long mlen,
|
||||||
const unsigned char *sk
|
const unsigned char *sk, /* Curve/Ed25519 private key */
|
||||||
|
const unsigned char *pk, /* Ed25519 public key */
|
||||||
|
const unsigned char *random /* 64 bytes random to XOR into nonce */
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "sha512.h"
|
#include "sha512.h"
|
||||||
#include "sph_sha2.h"
|
#include "sph_sha2.h"
|
||||||
|
#include "zeroize.h"
|
||||||
|
|
||||||
int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input,
|
int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input,
|
||||||
unsigned long long len)
|
unsigned long long len)
|
||||||
@ -8,6 +9,6 @@ int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input,
|
|||||||
sph_sha512_init(&ctx);
|
sph_sha512_init(&ctx);
|
||||||
sph_sha512(&ctx, input, len);
|
sph_sha512(&ctx, input, len);
|
||||||
sph_sha512_close(&ctx, output);
|
sph_sha512_close(&ctx, output);
|
||||||
|
zeroize((unsigned char*)&ctx, sizeof(ctx));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "crypto_hash_sha512.h"
|
#include "crypto_hash_sha512.h"
|
||||||
#include "ge.h"
|
#include "ge.h"
|
||||||
#include "sc.h"
|
#include "sc.h"
|
||||||
|
#include "zeroize.h"
|
||||||
|
|
||||||
/* NEW: Compare to pristine crypto_sign()
|
/* NEW: Compare to pristine crypto_sign()
|
||||||
Uses explicit private key for nonce derivation and as scalar,
|
Uses explicit private key for nonce derivation and as scalar,
|
||||||
@ -11,23 +12,31 @@
|
|||||||
int crypto_sign_modified(
|
int crypto_sign_modified(
|
||||||
unsigned char *sm,unsigned long long *smlen,
|
unsigned char *sm,unsigned long long *smlen,
|
||||||
const unsigned char *m,unsigned long long mlen,
|
const unsigned char *m,unsigned long long mlen,
|
||||||
const unsigned char *sk
|
const unsigned char *sk, const unsigned char* pk,
|
||||||
|
const unsigned char* random
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
unsigned char pk[32];
|
|
||||||
unsigned char az[64];
|
|
||||||
unsigned char nonce[64];
|
unsigned char nonce[64];
|
||||||
unsigned char hram[64];
|
unsigned char hram[64];
|
||||||
ge_p3 R;
|
ge_p3 R;
|
||||||
|
int count=0;
|
||||||
memmove(pk,sk + 32,32);
|
|
||||||
|
|
||||||
*smlen = mlen + 64;
|
*smlen = mlen + 64;
|
||||||
memmove(sm + 64,m,mlen);
|
memmove(sm + 64,m,mlen);
|
||||||
memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */
|
memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */
|
||||||
crypto_hash_sha512(nonce,sm + 32,mlen + 32);
|
|
||||||
|
/* NEW : add prefix to separate hash uses - see .h */
|
||||||
|
sm[0] = 0xFE;
|
||||||
|
for (count = 1; count < 32; count++)
|
||||||
|
sm[count] = 0xFF;
|
||||||
|
|
||||||
|
crypto_hash_sha512(nonce,sm,mlen + 64);
|
||||||
memmove(sm + 32,pk,32);
|
memmove(sm + 32,pk,32);
|
||||||
|
|
||||||
|
/* NEW: XOR random into nonce */
|
||||||
|
for (count=0; count < 64; count++)
|
||||||
|
nonce[count] ^= random[count];
|
||||||
|
|
||||||
sc_reduce(nonce);
|
sc_reduce(nonce);
|
||||||
ge_scalarmult_base(&R,nonce);
|
ge_scalarmult_base(&R,nonce);
|
||||||
ge_p3_tobytes(sm,&R);
|
ge_p3_tobytes(sm,&R);
|
||||||
@ -36,5 +45,11 @@ int crypto_sign_modified(
|
|||||||
sc_reduce(hram);
|
sc_reduce(hram);
|
||||||
sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */
|
sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */
|
||||||
|
|
||||||
|
/* NEW: Dummy call to hopefully erase any traces of privkey or
|
||||||
|
nonce left in the stack from prev call to this func. */
|
||||||
|
volatile unsigned char* p = sm+64;
|
||||||
|
sc_muladd(sm+64,hram,hram,hram);
|
||||||
|
|
||||||
|
zeroize(nonce, 64);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
10
libaxolotl/jni/ed25519/additions/zeroize.c
Normal file
10
libaxolotl/jni/ed25519/additions/zeroize.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
void zeroize(unsigned char* b, unsigned long len)
|
||||||
|
{
|
||||||
|
unsigned long count = 0;
|
||||||
|
unsigned long retval = 0;
|
||||||
|
volatile unsigned char *p = b;
|
||||||
|
|
||||||
|
for (count = 0; count < len; count++)
|
||||||
|
p[count] = 0;
|
||||||
|
}
|
6
libaxolotl/jni/ed25519/additions/zeroize.h
Normal file
6
libaxolotl/jni/ed25519/additions/zeroize.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __ZEROIZE_H__
|
||||||
|
#define __ZEROIZE_H__
|
||||||
|
|
||||||
|
void zeroize(unsigned char* b, unsigned long len);
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sha512.h"
|
#include "crypto_hash_sha512.h"
|
||||||
#include "curve_sigs.h"
|
#include "curve_sigs.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
@ -10,6 +10,7 @@ int main(int argc, char* argv[])
|
|||||||
unsigned char signature[64];
|
unsigned char signature[64];
|
||||||
unsigned char msg[100];
|
unsigned char msg[100];
|
||||||
unsigned long long msg_len = 100;
|
unsigned long long msg_len = 100;
|
||||||
|
unsigned char random[64];
|
||||||
|
|
||||||
/* Initialize pubkey, privkey, msg */
|
/* Initialize pubkey, privkey, msg */
|
||||||
memset(msg, 0, 100);
|
memset(msg, 0, 100);
|
||||||
@ -21,21 +22,84 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
privkey[8] = 189; /* just so there's some bits set */
|
privkey[8] = 189; /* just so there's some bits set */
|
||||||
|
|
||||||
|
|
||||||
|
/* SHA512 test */
|
||||||
|
unsigned char sha512_input[112] = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
|
||||||
|
unsigned char sha512_correct_output[64] =
|
||||||
|
{
|
||||||
|
0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
|
||||||
|
0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
|
||||||
|
0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
|
||||||
|
0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
|
||||||
|
0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
|
||||||
|
0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
|
||||||
|
0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
|
||||||
|
0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
|
||||||
|
};
|
||||||
|
unsigned char sha512_actual_output[64];
|
||||||
|
|
||||||
|
crypto_hash_sha512_ref(sha512_actual_output, sha512_input, sizeof(sha512_input));
|
||||||
|
if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0)
|
||||||
|
printf("SHA512 bad #1\n");
|
||||||
|
else
|
||||||
|
printf("SHA512 good #1\n");
|
||||||
|
|
||||||
|
sha512_input[111] ^= 1;
|
||||||
|
|
||||||
|
crypto_hash_sha512_ref(sha512_actual_output, sha512_input, sizeof(sha512_input));
|
||||||
|
if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0)
|
||||||
|
printf("SHA512 good #2\n");
|
||||||
|
else
|
||||||
|
printf("SHA512 bad #2\n");
|
||||||
|
|
||||||
|
/* Signature test */
|
||||||
curve25519_keygen(pubkey, privkey);
|
curve25519_keygen(pubkey, privkey);
|
||||||
|
|
||||||
curve25519_sign(signature, privkey, msg, msg_len);
|
curve25519_sign(signature, privkey, msg, msg_len, random);
|
||||||
|
|
||||||
if (curve25519_verify(signature, pubkey, msg, msg_len) == 0)
|
if (curve25519_verify(signature, pubkey, msg, msg_len) == 0)
|
||||||
printf("success #1\n");
|
printf("Signature good #1\n");
|
||||||
else
|
else
|
||||||
printf("failure #1\n");
|
printf("Signature bad #1\n");
|
||||||
|
|
||||||
signature[0] ^= 1;
|
signature[0] ^= 1;
|
||||||
|
|
||||||
if (curve25519_verify(signature, pubkey, msg, msg_len) == 0)
|
if (curve25519_verify(signature, pubkey, msg, msg_len) == 0)
|
||||||
printf("failure #2\n");
|
printf("Signature bad #2\n");
|
||||||
else
|
else
|
||||||
printf("success #2\n");
|
printf("Signature good #2\n");
|
||||||
|
|
||||||
|
|
||||||
|
printf("Random testing...\n");
|
||||||
|
for (int count = 0; count < 10000; count++) {
|
||||||
|
unsigned char b[64];
|
||||||
|
crypto_hash_sha512_ref(b, privkey, 32);
|
||||||
|
memmove(privkey, b, 32);
|
||||||
|
crypto_hash_sha512_ref(b, privkey, 32);
|
||||||
|
memmove(random, b, 64);
|
||||||
|
|
||||||
|
privkey[0] &= 248;
|
||||||
|
privkey[31] &= 63;
|
||||||
|
privkey[31] |= 64;
|
||||||
|
|
||||||
|
curve25519_keygen(pubkey, privkey);
|
||||||
|
|
||||||
|
curve25519_sign(signature, privkey, msg, msg_len, random);
|
||||||
|
|
||||||
|
if (curve25519_verify(signature, pubkey, msg, msg_len) != 0) {
|
||||||
|
printf("failure #1 %d\n", count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b[63] & 1)
|
||||||
|
signature[count % 64] ^= 1;
|
||||||
|
else
|
||||||
|
msg[count % 100] ^= 1;
|
||||||
|
if (curve25519_verify(signature, pubkey, msg, msg_len) == 0) {
|
||||||
|
printf("failure #2 %d\n", count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("OK\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -39,7 +39,7 @@ public class Curve25519 {
|
|||||||
private static native byte[] generatePublicKey(byte[] privateKey);
|
private static native byte[] generatePublicKey(byte[] privateKey);
|
||||||
private static native byte[] generatePrivateKey(byte[] random, boolean ephemeral);
|
private static native byte[] generatePrivateKey(byte[] random, boolean ephemeral);
|
||||||
|
|
||||||
private static native byte[] calculateSignature(byte[] privateKey, byte[] message);
|
private static native byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
|
||||||
private static native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
|
private static native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
|
||||||
|
|
||||||
public static ECKeyPair generateKeyPair(boolean ephemeral) {
|
public static ECKeyPair generateKeyPair(boolean ephemeral) {
|
||||||
@ -55,7 +55,8 @@ public class Curve25519 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static byte[] calculateSignature(ECPrivateKey privateKey, byte[] message) {
|
static byte[] calculateSignature(ECPrivateKey privateKey, byte[] message) {
|
||||||
return calculateSignature(((DjbECPrivateKey)privateKey).getPrivateKey(), message);
|
byte[] random = getRandom(32);
|
||||||
|
return calculateSignature(random, ((DjbECPrivateKey)privateKey).getPrivateKey(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean verifySignature(ECPublicKey publicKey, byte[] message, byte[] signature) {
|
static boolean verifySignature(ECPublicKey publicKey, byte[] message, byte[] signature) {
|
||||||
@ -83,4 +84,15 @@ public class Curve25519 {
|
|||||||
return generatePrivateKey(privateKey, ephemeral);
|
return generatePrivateKey(privateKey, ephemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] getRandom(int size) {
|
||||||
|
try {
|
||||||
|
byte[] random = new byte[size];
|
||||||
|
SecureRandom.getInstance("SHA1PRNG").nextBytes(random);
|
||||||
|
|
||||||
|
return random;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user