How do I convert a curve point into a public key? #138
-
If I have an x25519 curve point (say, returned from |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 2 replies
-
Hi,
The curvePoint.toRawBytes() method does not directly yield the public key. It returns the raw bytes representation of the curve point.
To convert an x25519 curve point into a corresponding ed25519 public key, you need to perform a few additional steps. There are several public key encoding standards outthere, including X.509, SEC1, PKCS#1, PKCS#8, and raw byte representation.
The example I'll provide below uses the SEC1 standard.
1-
First, ensure that the curve point is on the Ed25519 curve. The hashToCurve function from the ***@***.***/curves/ed25519" package should guarantee this, but it's good to double-check.
2-
The x-coordinate of the curve point is used as the public key in Ed25519. However, Ed25519 public keys are not just the raw x-coordinate bytes. They are prefixed with a single byte that encodes the sign of the corresponding y-coordinate. This is done to ensure that the public key can be deterministically derived from the private key.
3-
To get the Ed25519 public key, you need to compute the y-coordinate from the x-coordinate (since you only have the x-coordinate), determine its sign, and then prefix the x-coordinate with the appropriate sign byte.
Unfortunately, I don't reckon that the noble-curves library provides such a built-in function to perform these steps. You may need to implement this functionality yourself or use another library that supports Ed25519 key generation.
I hope this helps! Let me know if you have any other questions.
Best regards,
De : Aljoscha Meyer ***@***.***>
À : paulmillr/noble-curves ***@***.***>
Sujet : [paulmillr/noble-curves] How do I convert a curve point into a public key? (Issue #137)
Date : 14/05/2024 13:05:34 Europe/Paris
Copie à : Subscribed ***@***.***>
If I have an x25519 curve point (say, returned from hashToCurve from ***@***.***/curves/ed25519"), how do I convert it into a corresponding ed25519 public key? Does curvePoint.toRawBytes() yield the public key, or something else? I cannot find any documentation on what exactly toRawBytes actually returns.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
can you clarify what’s your use case? |
Beta Was this translation helpful? Give feedback.
-
Thank you both for your replies 💜 @nflatrea Yes, if this is not implemented by noble, we'll just have to implement that part of the ed25519 spec ourselves. I was simply hoping to get around that. @paulmillr Good point asking for clarification, We might not actually need this. TLDR: We need to somehow transmit curve points over the wire, and converting them into public keys seems like a well-specified and widely-implemented choice. There are two independent use-cases: We want to use curve25519 for a multiset-homomorphic hash function, and we want to use curve25519 to implement private equality testing. For the homomorphic hash function, the underlying idea is simple: to hash a set of items, hash every individual item into the curve (via curve25519XMD:SHA-512_ELL2_RO, i.e., In principle, we could also just use noble's For the privat equality testing part, two peers need to exchange curve points and perform scalar multiplication on them, which again requires encoding them over the wire. Since crypto libraries often implement scalar multiplication functions that take an encoded public key as input (or at least, some raw byte array and not a curve point struct, compare, e.g., libsodium scalar_mult), it again seemed sensible to simply exchange public keys over the wire. But before we can do that, we must first hash the items for which we want to test for set intersection into the curve. Which is again a job for RFC9380, but leaves us with a curve point that we now need to encode into a public key to send to the other peer. Here again, we don't necessarily need to use public keys. We could also specify our own encoding of curve points, send that over the wire, and the other peer could decode and do scalar multiplication (with APIs that operate on actual curve points and scalars, not keys). |
Beta Was this translation helpful? Give feedback.
-
well, all ed25519 pubkeys are encoded in a way that is specified in toRawBytes. so it is a “public key”. it’s just that a concept of public key is different from a concept of point. public key has a specific private key but again you need curve25519, not ed25519 |
Beta Was this translation helpful? Give feedback.
-
Thank you for your help, I appreciate it a lot. TLDR: Is the output of toRawBytes in the format that the X25519 function expects for its input u-coordinate?
I did not understand this sentence. So here is how I understand things so far, primarily based off RFC7748:
Ok, I think I do understand your answer now. You are saying that the output of
Fair point. "u-coordinate of a curve point, encoded as expected by X25519" is what I should have used, I think? (No sarcasm here, I'm genuinely grateful that you are helping me become more precise in all of this!)
Makes sense, noted. If my understanding is correct by now, I guess my final remaining question would be "Where in the docs should I have looked so that I could have saved you the time of helping me out? |
Beta Was this translation helpful? Give feedback.
-
So... if I had never mentioned Curve25519 and defined everything in terms of Ed25519 (which is to say, the underlying edwards curve), then things would indeed work, right? Which is to say, hashToCurve returns a curve point on the edwards curve, and toRawBytes encodes that curve point (well, its y coordinate) using the encoding that is used to exchange Ed25519 public keys. |
Beta Was this translation helpful? Give feedback.
-
Great, thank you once again 🙏 |
Beta Was this translation helpful? Give feedback.
Correct.