Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Where is secp256k1, the most important curve in the history of cryptography and the one most used by real-world money applications in the world today?


I honestly can't tell if this is sarcasm or not.

In case it isn't, I'm not a cryptography engineer but those who are generally recommend against using secp256k1 in greenfield deployments, and it doesn't seem (to me at least) to be commonly used in existing software either (with one glaring exception of course).


Two glaring exceptions. Bitcoin and Ethereum both use secp256k1. As well as a host of smaller copycat cryptocurrencies of course.

I don’t believe your statement about seco256k1 being depreciated is correct. There are even tradeoffs between the two curve families, approximately equal software and hardware support, and legitimate reasons for preferring one over the other. They are approximately equal performant in practice, and both have high quality, high security implementations.


Two very closely-related exceptions, and a host of very closely-related copycats. Essentially, one problem space which makes up a small (I would say) percentage of the use of cryptography. In terms of daily impact on the lives of random folks, anyway.

I never said secp256k1 was depreciated (nor deprecated), I said that I have seen recommendations from people far more knowledgeable than I who say, effectively, don't use it unless forced to interoperate with Bitcoin. For example: https://soatok.blog/2022/05/19/guidance-for-choosing-an-elli...

The above link, in case you don't want to read through, basically says "use ed25519. If you can't do that, use secp256r1." This tracks with what I have read from others, and with the direction Filo is taking, so I consider it pretty good advice.


Yea I'm not going to dox myself on this site, but having actually submitted papers and presented at various cryptography conferences and worked as an applied cryptographer in this field for 10 years, I think I have more cryptographic domain experience than some random furry-avatar security blog writer. Nobody recommends secp256*r1*. Nobody. The Koblitz curve is strictly better.

And libsecp256k1 as an implementation has received as much or more review by professional cryptographers (including many members of the well-respected Stanford cryptography group) than any other curve implementation, including many of the curve25519 libraries. It is battle-tested and very secure. There is, essentially, a giant billion-dollar bounty on the security of this curve and the correctness of its implementation. And in the history of cryptocurrency, there has never, not once, been a theft of money due to a cryptographic weakness or implementation error in this library. Unlike curve25519, whose non-unity cofactor for example was a source of inflation bugs in CryptoNote-based projects (e.g. Monero), something which secp256k1 mathematically prevents from being possible in the first place.

If you want to start a new project and not have to worry about potential cryptographic vulnerabilities with your choice of curve or algorithm, there are very few options to pick from. Both curve25519 and secp256k1 are pretty much the only two options, and they are pretty equal in terms of trustworthiness. If you are doing anything novel with publicly-visible digital signatures, I would absolutely recommend secp256k1 over curve25519 due to the cofactor situation.


Eh, secp256r1 is fine. These days we even have complete formulas for it. secp256k1 is also fine, but in practice only ever used in somewhat legacy blockchain applications. (Recent ones tend to use pairing-friendly curves and more esoteric constructions on top.) Curve25519 is definitely a bad choice for anything but EdDSA and ECDH (and even there it's annoying) due to the cofactor, but ristretto255 reuses most of Curve25519's code and implements a prime-order group with a similar performance profile, so that's what I would pick if I needed a prime-order group in 2023.

Still, point is that there are pretty much two applications using secp256k1, who already have pretty good implementations for themselves, and the broader Go ecosystem doesn't get much from having us spend resources on maintaining secp256k1 alongside secp256r1 (which is definitely staying because of TLS and FIPS, amongst other reasons).

> I think I have more cryptographic domain experience than some random furry-avatar security blog writer.

oof


> Yea I'm not going to dox myself on this site, but having actually submitted papers and presented at various cryptography conferences and worked as an applied cryptographer in this field for 10 years, I think I have more cryptographic domain experience than some random furry-avatar security blog writer.

I believe the random furry-avatar blog writer works in the field as well, and writes under a pseudonym to "avoid dox[ing himself]. But I dunno, I'm not a regular reader

> Nobody recommends secp256r1. Nobody. The Koblitz curve is strictly better.

Well again, you have to see that from my perspective, your credentials are the same as the other guy. To be clear, I believe you; I just also believe the Soatok guy.

> Unlike curve25519, whose non-unity cofactor for example was a source of inflation bugs in CryptoNote-based projects (e.g. Monero).

Ah, I hadn't heard of that issue/those issues. I'll search for them tomorrow.

To be clear, I don't recall anyone ever saying secp256k1 is insecure, hence why I didn't want you to think I was calling it deprecated. I appreciate your insight.


> Ah, I hadn't heard of that issue/those issues. I'll search for them tomorrow.

It's pretty easy to summarize: basically for every curve25519 secret, there are 8 (cofactor=8) corresponding public keys, whereas for secp256k1 there is a 1:1 mapping between secret values and public keys. Normally this isn't an issue because when doing things like ECDH key agreement, or digital signatures, honestly who tf cares? Hence why djb opted for a cofactor curve for a small performance gain.

However as a broad generalization, zero-knowledge proofs basically operate by doing manipulation of public keys instead of the underlying secrets/committed values. So for every committed value there are 8 different possible commitments on the curve. Any time you have a zero-knowledge proof using curve25519, anyone can come by and (without knowing the secret value), manipulate it to create an entirely different, but valid proof.

In the case of Monero, spending authority derived from knowing a secret corresponding to an output, but you only ever revealed a "key image" which (simplifying greatly) was essentially a public key / elliptic curve point derived from that secret in a particular way. Double spends were prevented by keeping track of which key images had been seen already. But of course there are 8 possible key images, so every output was spendable up to 8 times. It was a number of years before this flaw was caught!

The cofactor is a huge foot-gun opportunity for anybody doing anything more complicated than simple ECDH, signing a message, or login authentication. It is the main reason why I don't use curve25519 in new protocols, nor recommend its use to others. Better to just not take the risk of getting burned.

There is a sub-curve (Ristretto) which is of prime order which can be used on top of curve25519. But doing zero-knowledge proofs of Ristretto operations is significantly more complicated due to the fact that it is a sub-curve, and the security arguments are subtly different in nontrivial ways. Easier to just use secp256k1 and know you are safe.


> There is a sub-curve (Ristretto) which is of prime order which can be used on top of curve25519.

I'm sure you are aware of this and are just abbreviating, but I think it's important to clarify this for other readers: Ristretto255 is not a sub-curve of Curve25519. It is not a curve at all. Ristretto is abstractly a prime-order group, and concretely a scheme for encoding group elements such that round-trip decode-and-encode produces the same element encoding.

It happens to have been designed to have the same order as the prime-order subgroup of Curve25519, for convenience of implementation, but it is possible to implement it using a different elliptic curve under the hood (though in general you're better to use Curve25519 under the hood for the same reason as avoiding Ed448: there are many more eyes working on solid implementations of that curve's arithmetic).

> But doing zero-knowledge proofs of Ristretto operations is significantly more complicated due to the fact that it is a sub-curve

Using Ristretto255 in zero-knowledge proofs is not much more complex than using an elliptic curve. It just isn't as _simple_ as using a plain elliptic curve, because you cannot witness a Ristretto element as a coordinate pair (x, y), again because Ristretto255 is not a curve. You instead have to witness the encoding of the group element, and then implement the decoding operation inside the circuit to constrain the encoding to its arithmetic representation (e.g. a Curve25519 curve point). This would actually be pretty straightforward to implement in a PLONK-style arithmetisation, but it's also only 12 field element multiplications and an inversion constraint, so it's perfectly feasible in R1CS as well. And thanks to the decoding constraints providing a firewall between the group element encoding and its arithmetic representation, once you have the latter you can safely just use it, and don't need to propagate subgroup checks or cofactor elimination throughout your protocol (like you would using Curve25519 directly).

In practice though, I agree that if you can use a prime-order elliptic curve, then you should definitely do so. Ristretto255 was designed at a time when people wanted to use cofactor curves for performance and curve-safety at the cost of group-safety; Ristretto255 provides that group-safety. Nowadays we have complete and performant formulae for all of the prime-order elliptic curves people want to use, so if you have the option then both secp256r1 and secp256k1 are decent options. But if you're in an ecosystem where Curve25519 is a necessary primitive, then Ristretto255 is a great option.

(Disclosure, since I'm not using a pseudonym here: Filippo and I are authors on the Ristretto IETF draft [0].)

[0] https://datatracker.ietf.org/doc/draft-irtf-cfrg-ristretto25...


I was abbreviating, but I see how it could cause confusion. Thank you for writing a more detailed clarification.


Why not just use Ristretto with Curve25519 to avoid cofactor issues?


Ristretto adds complexity over just using secp256k1, which also has very good Rust support, is quite fast and well-optimized, compiles to WASM, and supports ECDSA, ECDH, and Schnorr key aggregation, so it's quite full-featured.


Well the scamcoin guys can just use separate library for it. I doubt any of the crypto uses would care about timing attacks either


The libsecp256k1 library has been ahead of standard curve25519 implementations in terms of protection against timing attacks, implementation foot-guns, and runtime efficiency.


I wouldn't call it the most important curve in the history of cryptography lol, but there's an implementation in geth: https://github.com/ethereum/go-ethereum/tree/master/crypto/s...


It has no mainstream use outside of cryptocurrency projects, which already require major dependencies and will never be implemented in the stdlib. Prime facie, it doesn't belong in stdlib.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: