From 1eb3884b7a0de474dcbc90083e1ea4fbfb9cee4f Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Thu, 24 Jul 2014 11:24:54 -0700 Subject: [PATCH] Update to latest ref10-extract ed25519 --- libaxolotl/jni/curve25519-jni.c | 6 +- libaxolotl/jni/ed25519/additions/curve_sigs.c | 57 ++++++------- libaxolotl/jni/ed25519/additions/curve_sigs.h | 41 +++++++--- libaxolotl/jni/ed25519/additions/sha512.c | 3 +- .../jni/ed25519/additions/sign_modified.c | 27 +++++-- libaxolotl/jni/ed25519/additions/zeroize.c | 10 +++ libaxolotl/jni/ed25519/additions/zeroize.h | 6 ++ libaxolotl/jni/ed25519/main/main.c | 76 ++++++++++++++++-- libaxolotl/libs/armeabi-v7a/libcurve25519.so | Bin 90172 -> 90172 bytes libaxolotl/libs/armeabi/libcurve25519.so | Bin 90168 -> 90168 bytes libaxolotl/libs/x86/libcurve25519.so | Bin 114752 -> 114752 bytes .../libaxolotl/ecc/Curve25519.java | 16 +++- 12 files changed, 188 insertions(+), 54 deletions(-) create mode 100644 libaxolotl/jni/ed25519/additions/zeroize.c create mode 100644 libaxolotl/jni/ed25519/additions/zeroize.h diff --git a/libaxolotl/jni/curve25519-jni.c b/libaxolotl/jni/curve25519-jni.c index 305370ac69..5b4cc2f432 100644 --- a/libaxolotl/jni/curve25519-jni.c +++ b/libaxolotl/jni/curve25519-jni.c @@ -76,17 +76,19 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_c } 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); 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); - curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength); + curve25519_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); diff --git a/libaxolotl/jni/ed25519/additions/curve_sigs.c b/libaxolotl/jni/ed25519/additions/curve_sigs.c index b002dc8748..b92b136cd3 100644 --- a/libaxolotl/jni/ed25519/additions/curve_sigs.c +++ b/libaxolotl/jni/ed25519/additions/curve_sigs.c @@ -4,11 +4,10 @@ #include "crypto_sign.h" 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 */ - 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; + 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, @@ -17,49 +16,49 @@ void curve25519_keygen(unsigned char* curve25519_pubkey_out, convert Curve25519's "montgomery" x-coordinate into an Ed25519 "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_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); + 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); + 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) + const unsigned char* curve25519_privkey, + const unsigned char* msg, const unsigned long msg_len, + const unsigned char* random) { 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 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); + /* Convert the Curve25519 privkey to an Ed25519 public key */ ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); - ge_p3_tobytes(ed_keypair + 32, &ed_pubkey_point); - sign_bit = ed_keypair[63] & 0x80; + ge_p3_tobytes(ed_pubkey, &ed_pubkey_point); + sign_bit = ed_pubkey[31] & 0x80; /* 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); /* 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) +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; @@ -87,11 +86,15 @@ int curve25519_verify(unsigned char* signature, /* Copy the sign bit, and remove it from signature */ ed_pubkey[31] |= (signature[63] & 0x80); - signature[63] &= 0x7F; - memmove(verifybuf, signature, 64); + verifybuf[63] &= 0x7F; + memmove(verifybuf+64, msg, msg_len); /* 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); } diff --git a/libaxolotl/jni/ed25519/additions/curve_sigs.h b/libaxolotl/jni/ed25519/additions/curve_sigs.h index 706f7db644..97d8a165f8 100644 --- a/libaxolotl/jni/ed25519/additions/curve_sigs.h +++ b/libaxolotl/jni/ed25519/additions/curve_sigs.h @@ -2,24 +2,45 @@ #ifndef __CURVE_SIGS_H__ #define __CURVE_SIGS_H__ -void curve25519_keygen(unsigned char* curve25519_pubkey_out, - unsigned char* curve25519_privkey_in); +void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ + const unsigned char* curve25519_privkey_in); /* 32 bytes */ -void curve25519_sign(unsigned char* signature_out, - unsigned char* curve25519_privkey, - unsigned char* msg, unsigned long msg_len); +void 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* random); /* 64 bytes */ /* returns 0 on success */ -int curve25519_verify(unsigned char* signature, - unsigned char* curve25519_pubkey, - unsigned char* msg, unsigned long msg_len); +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 */ + 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( unsigned char *sm,unsigned long long *smlen, 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 diff --git a/libaxolotl/jni/ed25519/additions/sha512.c b/libaxolotl/jni/ed25519/additions/sha512.c index 9540ef467f..b3c3867fd9 100644 --- a/libaxolotl/jni/ed25519/additions/sha512.c +++ b/libaxolotl/jni/ed25519/additions/sha512.c @@ -1,5 +1,6 @@ #include "sha512.h" #include "sph_sha2.h" +#include "zeroize.h" int crypto_hash_sha512_ref(unsigned char *output ,const unsigned char *input, 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(&ctx, input, len); sph_sha512_close(&ctx, output); + zeroize((unsigned char*)&ctx, sizeof(ctx)); return 0; } - diff --git a/libaxolotl/jni/ed25519/additions/sign_modified.c b/libaxolotl/jni/ed25519/additions/sign_modified.c index c4b2d6f23e..5bc5cc7d5e 100644 --- a/libaxolotl/jni/ed25519/additions/sign_modified.c +++ b/libaxolotl/jni/ed25519/additions/sign_modified.c @@ -3,6 +3,7 @@ #include "crypto_hash_sha512.h" #include "ge.h" #include "sc.h" +#include "zeroize.h" /* NEW: Compare to pristine crypto_sign() Uses explicit private key for nonce derivation and as scalar, @@ -11,23 +12,31 @@ int crypto_sign_modified( unsigned char *sm,unsigned long long *smlen, 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 hram[64]; ge_p3 R; - - memmove(pk,sk + 32,32); + int count=0; *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); + + /* 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); + /* NEW: XOR random into nonce */ + for (count=0; count < 64; count++) + nonce[count] ^= random[count]; + sc_reduce(nonce); ge_scalarmult_base(&R,nonce); ge_p3_tobytes(sm,&R); @@ -36,5 +45,11 @@ int crypto_sign_modified( sc_reduce(hram); 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; } diff --git a/libaxolotl/jni/ed25519/additions/zeroize.c b/libaxolotl/jni/ed25519/additions/zeroize.c new file mode 100644 index 0000000000..a0de1ef2fe --- /dev/null +++ b/libaxolotl/jni/ed25519/additions/zeroize.c @@ -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; +} diff --git a/libaxolotl/jni/ed25519/additions/zeroize.h b/libaxolotl/jni/ed25519/additions/zeroize.h new file mode 100644 index 0000000000..f4318795f6 --- /dev/null +++ b/libaxolotl/jni/ed25519/additions/zeroize.h @@ -0,0 +1,6 @@ +#ifndef __ZEROIZE_H__ +#define __ZEROIZE_H__ + +void zeroize(unsigned char* b, unsigned long len); + +#endif diff --git a/libaxolotl/jni/ed25519/main/main.c b/libaxolotl/jni/ed25519/main/main.c index 657b59f39a..ab451bf4e6 100644 --- a/libaxolotl/jni/ed25519/main/main.c +++ b/libaxolotl/jni/ed25519/main/main.c @@ -1,6 +1,6 @@ #include #include -#include "sha512.h" +#include "crypto_hash_sha512.h" #include "curve_sigs.h" int main(int argc, char* argv[]) @@ -10,6 +10,7 @@ int main(int argc, char* argv[]) unsigned char signature[64]; unsigned char msg[100]; unsigned long long msg_len = 100; + unsigned char random[64]; /* Initialize pubkey, privkey, msg */ memset(msg, 0, 100); @@ -21,21 +22,84 @@ int main(int argc, char* argv[]) 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_sign(signature, privkey, msg, msg_len); + curve25519_sign(signature, privkey, msg, msg_len, random); if (curve25519_verify(signature, pubkey, msg, msg_len) == 0) - printf("success #1\n"); + printf("Signature good #1\n"); else - printf("failure #1\n"); + printf("Signature bad #1\n"); signature[0] ^= 1; if (curve25519_verify(signature, pubkey, msg, msg_len) == 0) - printf("failure #2\n"); + printf("Signature bad #2\n"); 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; } diff --git a/libaxolotl/libs/armeabi-v7a/libcurve25519.so b/libaxolotl/libs/armeabi-v7a/libcurve25519.so index fdde5d0672a67d11a04bdde1a9473057108b8c2d..1dd438f09c9541246865ae3dac30cea49e31ce9f 100755 GIT binary patch delta 7441 zcmai(d3+Sbw#Tby%OqqVNC*fLCKJJ7PY57HxJ)1vgf-woltoq<5Hu)Pw&=79%6;ZZ zybUJs;UX7MCt=CNVF{W*P?W#}1wq_cq8C1w1cjcbu{+5y^M2J`W9GyC=+1L*_xt zrwFlfUJZQ(_NAPwp>rN0M2yq@zhvBnkT0Je=KiNLBr!4o@T|>*Oyu?&@Zy&VX-LxjuNyst?1T01X?lef9ao^k z1l}M4+>!;GS+}Qwk5^zI+|G8i!bb?(6gHqW;5(IsJiz&%U=RFVoIe9Mf+usn?m$|gPVm~ptt*rZUIzcp+`a;w13UIp8^AX3_uzcaHQ*ix35n+`@(1|F zM;H*cf(_Wy&qBzqBdr0Zfgj(5bmR>dfyeA>o$*TWYVZ?0z-!=`-Gn4_mcZ?!{C9!B z0!Qozz`ug|mU+l|RP;axkv+T(&I0Gh>mv+-*JH-nJb)9))af`OC7g4>)tGT)$)5$c z!Gt3ALS~Oz(f#1TA7jGW1U)h2A}a2p!BE~|3-|`OGv_WinJYgbWCxaxE!iXBQLsby568l)uN021}wU7_S8voF`L##Lt0C*;v)&f5oPDOQ^A!{_GJ-9d~E=4qT+It!}fdF4<^`>$N)~>!{37wzG=N^egWr#`||#cI86oM zNRp?54}gau*R%m-qM`~F5uOS@@hr{=o&*vI=iS2#{DZAa4N|){+oj32_R{XSPSU4gQO0q+ z+)H}3V<%4!kR37u@+gE|Uu5yk2 zPeIy4*fSHd7(&?!xlniv5_uM)FdFhOBp>n|q!WZae}TN9m0JJF=Eb4X+@wb(F)3a; zlVojgYjq%OZ_U#8NnIs5DKWMKh$UB&bo|PI$5Xi82}^#x+wpkhYMyka-aH zv(XPS3&NfhU6CxV2SPs%nFD#A5S(i~lORt@>78A%Sf<)L$iivTn$80}=u8GBq4syC zC*q!CdJ0}im_|aH>iXR<)xCG4ZQaH?t9nd(lvAW_T{^dwr>yt6QcTn+6;Y#Gs_D}CsVqty7u33e7HX#@ zV^iJ6Ejqu-nK;^RVfNQKGuk`wHI1I6)96{16d7q673762sct*%MF-LgDtVElO8dJe zr5d+9#c)1J^`Ub+ZM$XKpX{V&U-eB{8q@VrVVQqR*AZqQ|Y_l~Wx_gY({si34w5R*vfd(RNQmiqOXVcUH>7yWmbn}>e4OPl+Q5k%?7KJVL{ zsL!F#d98y(io^fkeXp22M{n60b6&PJl4Y3t#=Kg*`TQu5#G^Rk2haHi?j63*LY-bg z9u;)c6xy2-xuD5G( zk_ua(vsIAI!EtDoC7T$58&MFvX(TF|Yv38DO^I0{%=&YLHBXWuA za@c7WX8**kP3lPdT6c%h->Mhw>(r5H8Sbs4gmWQf)UBAn<(P-6DVsMrR>Vj9m2ddu z5^B;$YhqzZOyg^-Go)h!JA3xAaS_?sgh}9-{;b9Xh7&e2utAVXGt)7F1zH`Eufbl3 z@&dsYNN7XkAuV9oFQaa_z?O~8>oVrmr5U44D^^oeQfR8|F*<37(JsfEYHE5&`K94o z)l@TzZdN@b)64-EnM;juS&s%GH}U->%GDYDBtW7`y mR||FqDV|1fMCGSRrXAp1dgs(TlmB<1b7P)|}j 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 delta 7353 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 delta 16881 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 diff --git a/libaxolotl/libs/x86/libcurve25519.so b/libaxolotl/libs/x86/libcurve25519.so index 55b968a35de823066522b2711a5ab5c746c3dd19..1bff1ccf1ec724737ce060715fb8bdf4438b06b5 100755 GIT binary patch delta 8874 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 diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java index 8c8d7ef9ce..18152d395a 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java @@ -39,7 +39,7 @@ public class Curve25519 { private static native byte[] generatePublicKey(byte[] privateKey); 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); public static ECKeyPair generateKeyPair(boolean ephemeral) { @@ -55,7 +55,8 @@ public class Curve25519 { } 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) { @@ -83,4 +84,15 @@ public class Curve25519 { 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); + } + } + }