Thanks for giving me some time to mull over this folks. Apologies in advance, this is a long post.
Thanks for this Paul, it's very helpful, and gave me a lot to think about.
Part of me is beginning to wonder how much of this is less a matter of the actual structure of the repository, and more a matter of its emphasis.
I believe that there is meaningful value in having the current Crypto module exist, in at least some form. Having a clearly delineated space where the API is cross-platform with the best possible implementation for all supported platforms is useful for a wide range of development work, including some server work. But Swift Crypto is not a server library, it's a Swift library, and the goal is that we are serving the whole community, not just the Server piece of it.
So, given that it's clear we're not supporting the Server community well enough, I understand this feedback to be asking for an investigation into how the server community can get better support. But I don't think we should do it at the cost of hurting other communities that rely on Crypto.
This brings me to my question, and a suggestion. My question is: what problems have we encountered due to the slower rate of evolution of the Crypto module? I don't think answers to this can be "we couldn't get x algorithm in": in my view it's a non-goal to get non-x-platform algorithms into the x-platform piece, and the new plan is that CryptoExtras (or its equivalent) will be a fully-supported piece of the library. So the real aim would be adding API to the existing types there, or making changes to the implementation.
I can think of only two issues in recent memory where this has been relevant, Sendable and a proposal to change the layout of the digest types. For Sendable, I think I have a plan for how we could address that issue, and for the digest types this is mostly an issue of us acting as your representative internally. Changes in the cross-platform implementation can be made: they just can't be made fast, and they require that the Swift on Server team that maintain Swift Crypto are held to account to actually get them through. But they can be done.
As for my suggestion, here it is: what if we changed the name of CryptoExtras, and changed the emphasis? This would be a two-step process.
First, a new name. Paul's feedback makes it clear that an issue with CryptoExtras is that it feels secondary to Crypto, not complementary. That's a good piece of feedback. I am not in any way attached to the name, and if the community have a better one they'd like to use I'm all ears.
Second, a changed emphasis. What if we have CryptoExtras (or its replacement) @_exported import Crypto? This means that, for server use-cases, there is simply no reason to import Crypto at all. Users that wish to be sure that they are getting the CryptoKit interface can still do so, but users that want all the crypto support can just import CryptoExtras and be on their way.
This also allows a band-aid on the current Sendable approach: we can compiler-guard some @retroactive Sendable conformances on the types defined in Crypto. For server use-cases, we generally own those types. For client use-cases we don't, but as Sendable conformance is simply a marker protocol I don't believe there is any particular concern with the retroactive conformance (though I'd like to have @Joe_Groff fact-check that). We can then remove the conformance at such a time as it becomes available in CryptoKit.
If we combined this with the proposed ease of contribution, does this address the bulk of the problems? If not, what am I missing?
I think this is a really interesting sub-piece of feedback, and thanks for raising it Alexander. Rest assured I have not lost sight of the bitcoin curve.
A question we have here is: what is the point of Swift Crypto? This relates to the discussion Paul and I have had about philosophy: what are we trying to serve?
I am nervous about having Swift Crypto be effectively a "standard library" for cryptography. I don't think this serves a healthy community, as it forces this high barrier to contribution. This high barrier will always be there, because any contribution that others make must be maintained in perpituity by us. As you note, maintenance requires funding and time. Many algorithms are not worthy of that time, but importantly, many more can be just as effectively implemented by others, thereby spreading the work and the cost.
An example here is the recent proposal to add XSalsa20Poly1305 for compatibility with libsodium. As the author notes, BoringSSL does not have an implementation of XSalsa20, so this would require a greenfield implementation.
In my view, this is a perfect opportunity to take something out of Crypto. @0xTim has expressed his displeasure with the build times required for BoringSSL: having things outside of Crypto allows the opportunity for interested users to avoid that build time altogether, as well as take a reduced binary size, while not costing anything more in the case that they also need Crypto. It also gives implementers agency (they don't have to get permission from maintainers to make changes) and control over timelines (they don't have to wait for me to get a spare moment to conduct reviews).
In my view, it is not a good idea for us to try to produce a monolithic library with support for all cryptography. secp256k1 is a good example. As I noted in our discussion, BoringSSL lacks an optimized implementation of secp256k1:
Additionally, BoringSSL does not have an optimised implementation of secp256k1. We can have BoringSSL implement it using the custom curves functionality, but this will make the performance of secp256k1 substantially worse than the optimised NIST curves currently exposed via Swift Crypto. Thatâs an unfortunate and surprising performance cliff to hit for unsuspecting users who may reasonably assume that the performance of these curves could be expected to be broadly similar.
This remains true, and raises a question: if we were to add secp256k1, would we accept a slow implementation, or would we need to find an acceleration library? If the latter, this is another C library that must be built and linked in order for Crypto to provide it, further harming the build times that the community is already unhappy with.
This takes us to Alex's post on the philosophy of cryptographic libraries. Thus far, CryptoKit is very close to "one right answer". Swift Crypto started that way, but has intentionally moved in response to feedback from the OSS community towards something much closer to "all secure algorithms". For now, this is where I want us to be.
However, I want to call out an important part of Alex's post that may have been missed:
In some sense all of these libraries have a place in the world. In another sense, the more use cases (including the need to be interoperable) that can be served from âOne Right Answerâ libraries, the more secure outcomes weâre likely to get.
In many ways, the thing that makes Crypto valuable is its access to a copy of BoringSSL. That means there is a strong incentive to include anything that would require or benefit from a copy of BoringSSL (or similar) to achieve its goals. However, the moment we don't need BoringSSL to do something, we should as a community ask ourselves whether a "one right answer" library is a better fit. I continue to believe this is true for secp256k1, but I remain open to feedback that the wider community doesn't agree.