19:08:52 wow this is really interesting. In Java, I can do 2206 variable base scalar mults per second, but 90k conversions between ed25519 ad curve25519 points per second 19:09:46 so it's faster to convert an ed25519 point to a curve25519 point, scalarmult it, and then convert it back to an ed25519 point (vs just doing a varbase scalar mult on the ed25519 point directly) 19:10:29 knaccc: are you deserializing first and converting both coordinates? 19:13:24 UkoeHB the ed25519<->curve25519 conversion doesn't require serializing/deserializing, because they're just 32 byte little endian unsigned ints. after the conversion, then yes the curve25519 scalarmult lib must be decoding and later encoding the point 19:14:26 i can't do a direct comparison between ed25519 and curve25519 in my dev environment, because they're totally different libraries with all sorts of inefficiencies due to the java object overheads etc 19:14:30 are you sure? are the ed25519 and curve25519 encoding schemes the same? 19:15:19 UkoeHB it seems to all be working. Ed25519 compressed points are just a "y" coordinate, and Curve25519 points are just a "u" coordinate 19:15:51 is the sign of the other coordinate preserved when converting? 19:16:45 there doesn't seem to be any need for messing with the sign 19:16:45 the encoding scheme pastes the sign of the other coordinate in the MSB 19:17:04 yeah i've seen curve25519 code do that 19:17:34 but the libsodium conversion code doesn't do anything like that when doing ed25519->curve25519 conversion 19:17:38 and i'm not doing it either 19:17:47 and i've been testing ECDH exchanges and things seem to work 19:17:51 oh libsodium has its own conversion code? 19:18:16 it does in the ed25519->curve25519 direction. https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_sign/ed25519/ref10/keypair.c#L46 19:26:05 they are testing `ge25519_is_on_main_subgroup()`, although for our use-case it might not be needed 19:26:59 honestly I am quite confused about the sign question 19:28:02 UkoeHB i did this test: pick scalars a and b, and in ed25519 derive A=aG, B=bG and S=aB. Then I convert A from ed25519 to curve25519, and in curve25519 calculate b * A_curve25519. I then convert the result back to an ed25519 point S', and I can verify that S==S' 19:28:56 so everything seems to be working perfectly 19:29:01 hmm 19:30:49 My report seems to have been approved. A hell lot of links there: 19:30:49 https://www.reddit.com/r/Monero/comments/sfs195/mjs_dev_report_2022_jan/ 19:34:01 oh wait, actually that's not what my test does. actually i keep b * A_curve25519 as a curve point, and convert the ed25519 aB result to curve25519 and check they're the same 19:34:11 i'll test converting them to ed25519 instead 19:34:27 s/i keep b * A_curve25519 as a curve point/i keep b * A_curve25519 as a curve25519 point 19:36:49 ah ok it fails when i convert back the curve25519 result to ed25519, so maybe this is only easy in the ed25519->curve25519 direction 19:38:03 you're right, it only passes my test sometimes 19:38:06 e.g. a failure here: 19:38:08 b125f55e9a791496e077868b15364629a501c8436c39b52e511574439d8d525e 19:38:10 b125f55e9a791496e077868b15364629a501c8436c39b52e511574439d8d52de 19:38:14 so i need to encode the sign 19:38:29 but only in the curve25519->ed25519 direction 19:40:01 so i need to recover the x coordinate from the y coordinate when doing curve25519->ed25519 19:40:22 but that's great for our use case, because we only need to go in that direction if the view tag matches 19:40:33 so it doesn't matter if that's more expensive 19:41:01 why do you need to go back to ed25519? 19:41:18 the resulting key is always hashed 19:42:31 UkoeHB depends on whether we want to use Hs(curve25519 shared secret)G + D or stick to Hs(ed25519 shared secret)G + D 19:43:32 i think i'd be happy just using the curve25519 ECDH derivation everywhere 19:46:23 knaccc: you can try `a * B ?= a * (-B)` 19:46:51 maybe `curve25519(ed25519(B)) == curve25519(ed25519(-B))` 19:52:44 knaccc: https://crypto.stackexchange.com/questions/68121/curve25519-over-ed25519-for-key-exchange-why 19:52:44 "Under the birational equivalence of Curve25519 and edwards25519, each X25519 public key corresponds to two possible Ed25519 public keys." 19:53:30 UkoeHB yes you're right, I did the test and they're the same (because I've not fixed the code yet) 20:00:22 UkoeHB are you saying you think it is not actually possible to convert back from curve25519 to ed25519 then, because of the ambiguity? 20:00:48 ah actually 20:01:10 i think the secret is to not just convert the curve25519 u coord back to the ed25519 y coord 20:01:22 i need to also determine the x coord 20:01:28 and then there won't be an ambiguity 20:02:19 the ed25519 x coord is just curve25519 u/v 20:02:44 but that does mean i need to recover v first 20:02:57 so there will be a performance hit 20:04:15 doh, i don't have a proper curve25519 library to do that for me 20:05:11 I don't think the reverse conversion is possible without losing the sign. You just have to 'pick one' 20:07:56 UkoeHB but if i know both x and y coordinates, instead of just the y coordinate, there is no sign ambiguity 20:08:14 so i just need to convert both x and y from u, instead of only getting y 20:09:09 after doing a variable scalar mult, the sign will change 20:09:44 it's not really a 'sign' in the first place, it is just whether the x coordinate is odd/even 20:11:25 UkoeHB here is the java code that normalizes the X and Y and then simply uses the sign of x to encode the sign into the 32 byte compressed representation: 20:11:32 final Ed25519FieldElement inverse = this.Z.invert(); 20:11:34 final Ed25519FieldElement x = this.X.multiply(inverse); 20:11:36 final Ed25519FieldElement y = this.Y.multiply(inverse); 20:11:38 final byte[] s = y.encode().getRaw(); 20:11:40 s[s.length - 1] |= (x.isNegative() ? (byte)0x80 : 0); 20:12:17 so i'm thinking that if i know X and Y properly, i can |= the 0x80 myself if necessary, depending on the value of X 20:13:28 (normalization required because this is one from P3 coordinate space) 20:14:15 You can try it, but I don’t think the ‘sign’ can be preserved. Odd/even of x will change at random during a multiplication. 20:15:31 UkoeHB you may well be right, i'll need to think it through. i'll let you know how the experiments go 20:16:30 still, this is moot if we just use the curve25519 derivation everywhere 20:16:32 so not a problem 20:21:52 UkoeHB lol you're totally right, my brain wasn't processing properly what you asked me to test earlier. if curve25519(ed25519(B)) == curve25519(ed25519(-B)), then there is no way the sign can be recovered 20:57:59 there is an interesting technique that people use when they want to publish a Curve25519 public key, but sign using Ed25519. They use their private key to derive the Ed25519 properly, and then store the sign of the proper Ed25519 public key into the unused bits of the scalar in the schnorr signature 20:58:21 so then the person validating the signature can convert the curve25519 public key to the ed25519 point with the correct sign 20:59:28 as documented here: https://moderncrypto.org/mail-archive/curves/2014/000293.html 21:01:28 hmm interesting 21:07:13 > The Ed25519 public key's sign bit is conveyed in the signature. This allows an attacker to try to forge a signature for Alice based on either her actual Ed25519 public key or its negative. Since both are legitimate public keys, an attacker who can't break Ed25519 can't forge signatures for either. 21:07:13 Would this reduce bit security from 2^128 to 2^127? Aka not a practical impact? How do you think about that 21:07:49 jberman[m] it's just an interesting technique. i'm not suggesting at all that we should use it 21:07:55 we don't need it 21:09:16 but yes i think it just takes 1 bit off the security of the signature 21:13:14 Got it, just trynna learn :) 22:09:45 What is the best way to debug the functions at src/crypto/crypto.cpp? I'm struggling to execute the check_ring_signature. I have compiled the code and tried to execute the cncrypto but I always get 'invalid argument' so probably Im not executing it correctly. (Im using the terminal and gdb) 22:10:25 My c++ skills are pretty rusty too 22:11:01 Are there any bindings or some test file that I could easily call these functions? 23:14:32 git grep check_ring_signature tests 23:14:59 Piggy back on one of the files you find. performance_tests is minimal. 23:24:11 "git grep check_ring_signature..." <- Thanks moneromooo but I know where the files are but I don't know how to set breakpoints on them as I dont know how to execute them separated. Do you mean executing the ctests like recommended in tests/README ? 23:46:09 Sure. If you can't set breakpoints, you can add printf or log calls, that's what I usually do.