From 1cde4297b83c5ae7e6345181deaf2071defbb052 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Thu, 30 Apr 2015 14:48:19 -0700 Subject: [PATCH] Eliminate max message size for signatures. Dynamically allocate working buffers instead. Closes #3 --- android/jni/ed25519/additions/curve_sigs.c | 35 ++++++++++++++---- android/jni/ed25519/additions/curve_sigs.h | 2 - android/libs/armeabi-v7a/libcurve25519.so | Bin 135228 -> 135228 bytes android/libs/armeabi/libcurve25519.so | Bin 131128 -> 131128 bytes android/libs/mips/libcurve25519.so | Bin 235668 -> 235672 bytes android/libs/x86/libcurve25519.so | Bin 163904 -> 163904 bytes .../curve25519/java/curve_sigs.java | 21 +++-------- .../curve25519/FakeSecureRandomProvider.java | 4 ++ .../curve25519/Curve25519Test.java | 20 +++++----- 9 files changed, 46 insertions(+), 36 deletions(-) diff --git a/android/jni/ed25519/additions/curve_sigs.c b/android/jni/ed25519/additions/curve_sigs.c index 51f2052..fca6606 100644 --- a/android/jni/ed25519/additions/curve_sigs.c +++ b/android/jni/ed25519/additions/curve_sigs.c @@ -40,10 +40,10 @@ int curve25519_sign(unsigned char* signature_out, { ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ - unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */ + unsigned char *sigbuf; /* working buffer */ unsigned char sign_bit = 0; - if (msg_len > MAX_MSG_LEN) { + if ((sigbuf = malloc(msg_len + 128)) == 0) { memset(signature_out, 0, 64); return -1; } @@ -61,6 +61,8 @@ int curve25519_sign(unsigned char* signature_out, /* Encode the sign bit into signature (in unused high bit of S) */ signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ signature_out[63] |= sign_bit; + + free(sigbuf); return 0; } @@ -73,11 +75,18 @@ int curve25519_verify(const unsigned char* signature, fe ed_y; unsigned char ed_pubkey[32]; unsigned long long some_retval; - unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ - unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ + unsigned char *verifybuf = NULL; /* working buffer */ + unsigned char *verifybuf2 = NULL; /* working buffer #2 */ + int result; - if (msg_len > MAX_MSG_LEN) { - return -1; + if ((verifybuf = malloc(msg_len + 64)) == 0) { + 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 @@ -112,5 +121,17 @@ 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) */ - return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); + result = crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); + + err: + + if (verifybuf != NULL) { + free(verifybuf); + } + + if (verifybuf2 != NULL) { + free(verifybuf2); + } + + return result; } diff --git a/android/jni/ed25519/additions/curve_sigs.h b/android/jni/ed25519/additions/curve_sigs.h index cc46247..b3dbad0 100644 --- a/android/jni/ed25519/additions/curve_sigs.h +++ b/android/jni/ed25519/additions/curve_sigs.h @@ -2,8 +2,6 @@ #ifndef __CURVE_SIGS_H__ #define __CURVE_SIGS_H__ -#define MAX_MSG_LEN 256 - void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ const unsigned char* curve25519_privkey_in); /* 32 bytes */ diff --git a/android/libs/armeabi-v7a/libcurve25519.so b/android/libs/armeabi-v7a/libcurve25519.so index 09073d92d63c6c2799aec0f86e05e74cde863978..4e33854ad263026b56dbd97452d6b831306a89a6 100755 GIT binary patch delta 7000 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

$^mtDOphIZcB!RL dS2i!JB>nMa(|3WHeY81Mgm&dNv%08U{{eqt4yOPB delta 6798 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 F{{S9NH~jzr delta 6476 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 delta 5310 zcmZ8l4RBM}l|J`ANtUsVWx%ls2Ft}DCpe9gl7`<{Avgg-GisJ3PL?+6mLG?oVm5}D zK#)jqO29@k&-e-mMGF`_TUv=I)b1n*VIaB%y5)A>p&PH^3jieaZOkcJVIh!O^iVS^B61lsGs1Fkf!&Z~XMF@KjyEN}pQRs$JaU|FTU}u%O17})(4#B*dC-YGb|phE&cUi{ zB~@itv4Kv!A!!ceyy~yP5B(0g%E>=6!n@qRCK;K)EW@in2 z2|eG>p;MTVUx34*O~`OI%()!ziH9!hj0OTUDG5?4*Vw~^sYl056aL7Aa^3-TYLBeEReXX z1`No(HG+I7BDQxK5ql$8H0w|a77Q#x2D1STg1q4vw%njs(h~yrM6>~(UD|<%D(mrj zEZ~8GDOm%IF+2*l4E_h?v3g1Ftp1Dapn1|Z!oTbu%fH7=O9v5eGP^nvGv*Z&m1SL> zg6o&cSf$vX%4W$-ECOantdYFrC6~28LL2y*J-?RV23=*UZ)- zB?ay*RT_9Vc-cHSBq-X=Cx>p5p;q&^Ll=qn;}eI~2r)Ols`y`o@R?Ifo+(<>x^Ik~ zoQ9VUqoB*Cc;Z`2Uau(VJ(aQR`{uCgl36_QC2`4II&lPk-H+BvhFMK@ixzY($Zlh2Np!;_`M#~i*|WT|laB)i5~9blsc z&yAA^W1@GzL>T9uFM$s?pZ|*?&YM?WEP-3OFV%oG^QFmB^qI{sM@2IJ*ejn;79Yol zcf2a)wF%~%;U~md^Vea{z|Bf)vdB^=I`&&&9Yg&KFrx=E z=87Z1IuQ%nDQWn`VV8joKfNro(@g`1T~7KqD#RbF*T@f|jWQNpFONh6G9GP`2cs2% z08Ju~qaqX`H>}soebFUye{?o{?ShY(8=N8It{LnNvR9nP{7&ZkgA3(eGc5P;q#z~* zXG1AKZSGRq6RoI9;4kTeXoWjT!zdoDg4>%3TQPx1(<6^o(H>WYgJeCzB3jg9q1W&d zo7F`$3x5(byX-U{yqP_DRNIwL^(}U)?J1-gT@LzjWj@X5xvKpOhB;_jWepWf=h%ktVgNQPSsMFcmAW`=mNw%^*sO)Q+99qjt&RXOrnXFay-^p5^ zaWL9z#GaASiD5>NAv6fJIy+fPcsi()%N>1+xtb#yn!|SROo+{_m+#KqRJ`vi|8JHS#U-& zi~cegHoCCji7|DU;GkbbhfyS2N?qw%=s^@UD6)F7&xO()MoZhB0#$nfAv)h6f z>g|iSh?Zuys4HbT?CKAgkM5c#0V{Vs!SJhHlNhe<`i*EX4@D-+SZn-hWOt4T#kY1X zb4uq^rtQ;TiiY^1PlsCM+$YR`Kk+N!jj#Ld>q5Gx#IOJEMS=P8=T3f`(Oi3K6yAqB zPyL;^^v;!2-B(VDxDo-?xkw%niSGG}WsQx=<#M&W+}i!Ef0Sb}UN=ulC3#kF#AflVS? z?m+kTO>(8^UehWYgx|A%K;OWhy`+$!326PK>?#2QAA+P~> z99Y&dpf3Y`I|g(a{^REE#5~}f&H>G5$Myd_pqqe8jt}U)!1kP!?gjScr}Pcrnu3%b zX2ByG8=TVPaX#=mQrZhl7Nv9}&@n8f!$1#^4><1Plry-9!12K3pS7;5!@&E$TJxDP0t^8?m$Z%nW58aZ<14Md00#aK4xpKEf30;j&^2Q*epUzPa%0(V3mgh*DJ>a#Za;Gh zYuR=b6+-5#3ilEg?pEL3A|I5N{pufpD9zR_ST~^#ZNa*I>f9DNw6+X-G(AxGu%zFh-7UY+QWBdpw#?Nwj#1U{&{RgpqM=U~{V z9#Y^oVHi-~XKp)&r`1vnZ7~e(pR0{Z-aoYu;|-r{T@TA}wJMuX;tIF~*;&Zap?L>8 zy&;lP@}_p0xQ z5m*>QpIRQqrX(fRQX&#W|Kj=)2=Iy!b_l%0riTo%8R#mT_I;BQa`g~sC#oPi01 zLj0aYD@WTP&I7W8U{T*DgNlHSYAMvk)7_nbHGb}oSb;k*ZjAZj4xO7^?uGax0(aot z!ttj8Zf?0_=g$b-+H>p2?I8EG+*a~O3hv&xh2$=cds%J=xyj}@xEJMyn0sFIRtwW# zEx6<6MlAhB1I;aeli)U=za^lBOLyShNAb4?{ye}fKKHEL+TVL|f5kl&_fhHI3D_{i zEE4yrvn_^QhVG2)kiDh1r`nTTFZ35u)vZP;UUC;$ zuTNPwv);Jddh+OZ)Wud~6b|uf!DeHWIIEhWA}p$t!K01=rg6fF3IqLGYaa2n0pW}U zmgCNBhVeJ@GuX&m^2E>7*dUC1Rc#RK2X^0CKek)F3z3ZMQTtfMt&TxO_|yf~q>nP* z1&*e*a5AV3fgL%n7KGCFnn5B9oeUv$jD^Wl>LP@8-f5h#J!*E)D3!5grUPm1Z!vPk za`ki@mWDfcW=7fo1MbcZKMU1&=u1Fx)dJ68o!O+d{K!LDXZK;JeKUveeCOxh z^UnRrTiSeyZN9|DDtpdl5;S#ByLa_?H$x02En5 z>>d>Jp8#!xK8#}gc3}67LcC@1r-56i3h}nZp940!g~+k^$H2-WA>y@IeuRW3+KhkD zFmLA+A$WK$qa5zep9^u=O7nqd%n;(3<$oQ#Z{dIWPVnw~gm?wW`DcN?G9mtv6yuIK zj8`SZMa!QBe*Ho9VnUqoingEOJwbSYc?hVTF2tKw0k!{^Q1^d)IrEt)!XC@t2;OKArgLz{}a6SBNA6EJ~$rv`{;+A z;4OtAc^8Q)RK{=Y2k$&WKP<^+@V?_h1g!$z2fzOC8g_u^bdhL;&iNO?E4xV)TJbJ) zDgy=FZTWM-edtJW%#s;v0Y;39;<@Fa`ND*JzU++{VX`HXFHT>O$pYigcYX#6TE-RMlR8`GV) zBrRFAWXTgxEfUqgUS!lJ4K;q_%rf3~-qC#0x!UF(iSY`fqY805aEzsA1F`=F8ZQQ0 zHWzR>=G9H5CEfOIkAbF4i$VA93kO`1GA!8wTKqf)*A$LKz={E_HCdNU*nHRYb zez+hUW|3~tz=gTEEkpu@pMfzDLoH+&V(GXg#I39wYX{ymM~8AVGd!aqI4>d-G77>^ zM)cpeFf z^I{(6oX_~PYe<}_$T;8{Mn5%rT(?g6K#^#u(!Y%qDy5(}=e0LBct(lxNIFthw!aqh zM;iRx)__fqj4~!Cuc0`jBYA<=+hyp3yfmVDj1QFRS%G@}8fM3=eBk^MA5XfnQ>j&Lf!(h9PvC1P@#+Q9x3lSJiXM3Z z`#T6F+M#;=M6AV8R~2?g5W}+DwXI42j(w$iivN@k=FDo>FJlwIW~+96T%tSIR73}I zV}fMv!C@STJ+K#XCN}}?@@go^wQWYBYa62d-QI-GH8To1`sznY<+fR`ABw%o;E7#J z7X)Li3dUN6x948q?YS4|=1@TUH+%4}c#mgVTKLT#K8Z`m2D)7i4ebt3txSR;#CfXYAE(%~Pw{Zks8{2CDx>ST$b7Ka+q^T=4yKju&lm@%*HVWurFaN!G3FHCMINJ}c(Rs%(AZ!6a%$>9rT#ZWrZdXK*LGl6E#vx%XVE^Oeoa(l#5}i~sI8@+OmVqkr*I$K0s? zNptPveE6cDZ98xg9-s zv+)=5#6Bvc($;bNkw78&s{^#maioNO<*oe(Xbd?w6f+x9+&c0QWs>8`=}a-jhZJy} zp2lRM41Y*3JBp*EUDkg@KXF_sV$YNE=tp$bai!2Ao%ERVxhP32lvBItKF5S8YnDx2 zRIVL7EYEdOo^!)gjvp~qjyz0@9TTDqA%`*U=_%0}Tf>Lx0dhW9z$~$#b?Q-ap|;6P zQQI+^lX7H|sT!W*BmaR7d#OAUAN8(o-EoYrB|74AIM(0V(M?&j?G!C0ZRR-n^V5`0 zdu8A>4Wo#B3ov-VI8)*5L?8as+6b|YlV6;sv0DB(nHZ)~)F*SpG}<1?Hq~3Q>nx?n zrD3{DE6I_6f_rdj?th2KK>9jt%$d3Je3)+2Dstt(Gr-DRIsOcd*J>uo>N6NRr$D~Q zJTyh_2GYCo>KP2_`>`B0T4=6(<1D35wY)b%lkAzeuWDoi%!!py-5ygt>yX)(Xox%+p&|B{qW5 z;r1%nisZgt%pZa}Q(k7Z1!|d0y#VzD)OY1HsPVQ$e8ZiRQ!ir4bm)~bz!9ZT^W~o} z&@J{FsCBZ7)ezKo!mftnGPX%{KoejIv@oN^Hn-$Gp{AHIkoGVm?jAy+|7oe8z( ztomV1b#!n(Y{|wN?-@j1MCOB z1k^_(9$1B=-3P1~Z>phRE3XPqFjd*tm@v;&^^CYSwgdZty}*upO_lSFQXB6x)q}u_ z`w<7MDmT?$pnDF^@3)AXi*bN%oUJNgKX483=mJx<0X>hJN?b+$5)=vyV?Wnk^&)X8 z-Ux=4It&P`|1By6+MYI5%D>@%1``7}E;rRWpnIjMx`9V`!T%iwI){mYo*q-x0d2je z+6XK;tkem{BT6OXlO+ty1C|_B>Oo*XaG4j1?PE+1^n9w+x4`-nN)>z$8}?uoF#Ls5 zA)x0=*nsYC3=FISUSm9o_Tp2i1Bky4Nw5boh*Eh@XsCoX~g1o$#g~8 z6Ky#E*s$U$oF`l+Vi|s>@l96<&RA+;g@t@V`6tyPxk}M9X-{L==OC{@-iEvf*$?^D z_182lZ8TSyVLwH1pLbx>e+)uN5=+4s9#?b+`0e7x`bedjyp zyXWWLJ2aL>Hn;Cn@)XxFS?qRIY)Gq<^5*Txv`g4kBGB!aO$PaU-uqy2f zp5oszoiXa3%E(37xty^!Gp!7|=w8N-oAKA7GxLAcpFq3kGWH6P^3MTVa~S*LrU7k> zKz~aa>owypXvZ?#mf7F@2R|ndw7C#ykF;nEYh5T zd!h68a+Z(6=mz{7;BX$}H`e40=*%w|3z`M&hQ5B$lz$9eh61X-)nhwrpnC+u6 zQ$;8s%Z$6ATQMWE&G`M$j?XxA4QM}G2}jLw&Vpuzzk$w##9m!-Vg1-0QqM7QSh@$bcV~pF3a10q9;Q;Z^UaA>$nK*`RI|_L-rJHa7>c+JG(1# z#nKf^iq>lT>~0(Aij~hUt-WU7gw1jrI>k9Nt~>BI&E$6ivFRCRpA9j6aX=?*5RA&1 z0K=JP(XdglNw8_K3|Jy;A}k$tJ8T?m3hZv!T`-#Y!E6L$E)bkp=7!Ow!aT5Bv>~xe z{ITRRFFY<-(scnGYH~alSTbxl44c5XFonjIY9hgC7>*Ac1EbrfD`fzTzr#%K0FH;D zxS=ctWHKxYHWGF#Y^oL?ml2QQ91exq&@6$_tu2oGmDU-T5HXG^+V^oOyg(b_xMfnW zRJ8{Rjm&TXZVTKFpCwePW&}KHcogQz)On;8%!iRv zj5c-ZW-2mW4F|D;!3wnqyFP#j)qOyF;hwSnhZa1X8~*T!lpC9t<5-2N)%+h&uGWv+ zN5XFGoQ(}?18pG6^{TF5omvAK+^N2w3( ziI}h;3A+0VwcD6JzY!1Hu<0lkq#UoB0PZS?d#1t|m=fZ4HK;dH#}#S})!|bU(W#># z?sG5Z19ww`y@GlvSbn}N5DD&}hFKP{1cTYZ5)BpumTWM;1Jr5I1TfWLiD2{q3}hvP z(UT&O<|H!7>e&4(2sj23WSiJbS{44mRIlF<=V~<^Wq{umrF?gZUFd^9`B|w#;BoutI~WV07eyGtSmFnAu9An1ixvm0pkjfX{CnHdu7DH*+FZ;bJJt!&NI4&#j_P`R;k_Lxi-^E~4v_lyCE<6vNg`Q=hU6c~~nEo1j zXdV0;o5texiRN2%DYX}874Z35&#YnGqgiL)%`MvW+0&E*&DwLbw+-Lcj6L{&o3I(4 zjZNz`mp6wO)~@%?QIxX>Y7b^5+w3=eLZJ`$)b`xpHQb)`HmQHSrG5F!k8Qbck%-W$ zmzCK5`A6cLYMoEL&+Q}LB+*=5d+O;uoX2Xf6%MsedxLxz|4{o;;jg)JZHIRMGaY=e zHg07-U#^{7nWnt@TDhaB-ciJR9<*KY>1h0hur%@6d})1l6aS3cPR=1`us(S&pKswF zvFadCur1Fb=Lk`GkmvB7^`{OZfp?2rn|Y}%*GsX8`s!wWJGZCKCUtaH{qYu_#%)(- zlEe^)c)+&A5QD|mLwuX9DU%|rMfzcWpKY}vQbomK{+(_042nRs^2PROLwsJ1;kkEw4Sb>qd{PCj~QgZsxWoJik}{lD8SUh3qdluzB_PlT;* z(bmZ)D(zE5e^)Gg3uAJvj{M~yXN1CNePm>KJ6ni(6jZ)U80|IAp+-fa5lqV}Jn zebFPjoFL-6d6M;#Eh1j|?RlPTwPP*|#i?_AMwAcq#3Eh3M{P!k%=6qiyb3<=6S}0Y zOS+t}YWT{;+VeccdH~cTet(`%ilT43&ZWA1#TY?cInQsgX2RzcL&AJg{e5d+iJ+Qpq#Cm#0}ajlC_vMvOz6n9<#tpd##OD~|W-JmTZ zbOFoS3F;PqqXx>1VFYxi!98in6?ILcp7_>~>NAzXT2C;%@18BC`auI1)L7n2@ zMLxrtfzKeH7}O0~3YsV$=*DQ(piZ%tXbWhXc%A4~&?<3|Xfi&0?cy?~-s%C(5b-_m z=7T!Klpc61Ky$<+M5{ro#9B1CuLZR4jFkD9LgtNiX1^FwZdtHNQ8HsK`}Z{&-?Ep` z#@i`n){QnwdBoaS3&O@1vIEC2Dzb~=!#p5t-41#{ ztm?&5w1Xy!zw}}r5^#`mL{~2#<8QnoF9jxFm2x|<9l8UF!SPg8z6W|1J=LB6^zL9?EnWW2% zZ!jRRkZ>9r0)2SO90MlL)n($hQuYHg33GH=0rceR@&K@VJ`Qys@^H{{fZf1+V9P>X zZU*jrT$hbN-;=sz-=W|Y7!TM`tjnVB{75X( zU9ZdS!0s|#b^v$oMf`ho)P;e8zKgnC18fIY1C#N^-cEQ_N(a7@8i47*4bX=T*b3Z^P1Xl2Jc~RhKE)b9(t$4QqeY~{Xhiz5lqgcxPq@szgSb=l z=zLg`8@q*mHznYMiGGLCZ#1(0STR!aaZ|41af7YQR^hOLvSs+~hzBj33Qc&giStZc z0Hoi1dEy1h*CqV|-98O_4)zl471+Bl#@ MAX_MSG_LEN) { - Arrays.fill(signature_out, (byte)0); - return -1; - } - /* Convert the Curve25519 privkey to an Ed25519 public key */ ge_scalarmult_base.ge_scalarmult_base(ed_pubkey_point, curve25519_privkey); ge_p3_tobytes.ge_p3_tobytes(ed_pubkey, ed_pubkey_point); @@ -70,7 +63,7 @@ public class curve_sigs { public static int curve25519_verify(Sha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, - byte[] msg, long msg_len) + byte[] msg, int msg_len) { int[] mont_x = new int[10]; int[] mont_x_minus_one = new int[10]; @@ -80,12 +73,8 @@ public class curve_sigs { int[] ed_y = new int[10]; byte[] ed_pubkey = new byte[32]; long some_retval = 0; - byte[] verifybuf = new byte[MAX_MSG_LEN + 64]; /* working buffer */ - byte[] verifybuf2 = new byte[MAX_MSG_LEN + 64]; /* working buffer #2 */ - - if (msg_len > MAX_MSG_LEN) { - return -1; - } + byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ + byte[] verifybuf2 = new byte[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 diff --git a/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java b/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java index 8a97504..9316b62 100644 --- a/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java +++ b/j2me/src/test/java/org/whispersystems/curve25519/FakeSecureRandomProvider.java @@ -4,4 +4,8 @@ public class FakeSecureRandomProvider implements SecureRandomProvider { public void nextBytes(byte[] output) { } + + public int nextInt(int maxValue) { + return maxValue; + } } diff --git a/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java b/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java index ac93b0e..e2286ba 100644 --- a/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java +++ b/tests/src/main/java/org/whispersystems/curve25519/Curve25519Test.java @@ -130,18 +130,16 @@ public abstract class Curve25519Test extends TestCase { } } - public void testSignatureOverflow() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException { - Curve25519KeyPair keys = getInstance().generateKeyPair(); - byte[] message = new byte[4096]; + public void testLargeSignatures() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException { + Curve25519KeyPair keys = getInstance().generateKeyPair(); + byte[] message = new byte[1024 * 1024]; + byte[] signature = getInstance().calculateSignature(keys.getPrivateKey(), message); - try { - byte[] signature = getInstance().calculateSignature(keys.getPrivateKey(), message); - throw new InvalidKeyException("Should have asserted!"); - } catch (AssertionError e) { - // Success! - } catch (IllegalArgumentException iae) { - // Success ! - } + assertTrue(getInstance().verifySignature(keys.getPublicKey(), message, signature)); + + signature[0] ^= 0x01; + + assertFalse(getInstance().verifySignature(keys.getPublicKey(), message, signature)); } protected Curve25519 getInstance() throws NoSuchProviderException {