Hi all,
Nearly two years have passed since this post about Swift Crypto on all platforms.
That post aimed to discuss the state of the main cryptography library used today in Swift, its interaction with its closed source counterpart, CryptoKit, and the future of using said library for the server world and all other platforms and ecosystems Swift supports, both present at the time and that have arisen in the meantime.
The main pain points that post was trying to express, and to gather feedback on, were
- how the close coupling with CryptoKit was hindering the development of Swift Crypto;
- how the rest of the ecosystem was left with an underscored target (
_CryptoExtras) to propose changes to;
and in general how non-Apple platforms get a secondary treatment from Swift Crypto.
Swift Crypto is a great package, maintained by people who clearly know what they are doing: it's modern, safe and it was a windfall for the server ecosystem when it first landed. However, this was 6 years ago, and times have changed. Swift is much bigger now, it spans from the original Darwin usage to the server, Windows, embedded, Android and more. However, the points listed in the post above are still standing: apart from the rename of _CryptoExtras to CryptoExtras, the underlying situation hasn't changed. Swift Crypto is still an open source version of CryptoKit and is therefore completely reliant on the latter's updates. A few examples:
- I work on jwt-kit so I have a fair bit to do with cryptography. We were recently pointed to some research that showed Swift being 27x slower than Rust for HMAC JWT signing. JWTKit is definitely part of the problem there, however SwiftCrypto's HMAC is 3–5x slower than ring for the same BoringSSL primitives, with 7 allocations against 0(!), and its key setup alone is 13x slower (6 allocations). Following the findings, I've opened this PR Avoid some allocations in the HMAC initialiser by ptoffy · Pull Request #469 · apple/swift-crypto · GitHub. The PR does not touch any public declaration and is completely API/ABI stable: it's a simple and efficient performance improvement. Unfortunately, merging this is not at all easy nor guaranteed, as it requires CryptoKit changes, even if it's not a public API change. This obviously takes the matter out of my hands and outside of the open source process, often into Feedback Assistant (although not in this case, see Make HMAC authenticationCode and update inlinable by baarde · Pull Request #239 · apple/swift-crypto · GitHub), where contributors have no visibility. The inlinable PR was opened two years ago and feedback was filed, however the change is still not in version 5.0 (which was just released) so in the best case we will get this next year.
- @fpseverino has been trying to get MLDSA-44 into Crypto for a year now Add ML-DSA-44 to CryptoExtras by fpseverino · Pull Request #422 · apple/swift-crypto · GitHub. CryptoKit currently offers MLDSA 65 and 87 implementations. These are modern post-quantum algorithms with a respective medium and high security level. MLDSA-44 is the little sibling to these, offering a lower security level but faster signing speeds. JWTs do support MLDSA44 in their spec, however since CryptoKit does not offer this option, we don't have it in JWTKit either, since that would require us implementing it ourselves and therefore compiling a second version of BoringSSL. A PR for SLH-DSA was also opened two years ago at Add SLH-DSA post-quantum signatures to CryptoExtras by fpseverino · Pull Request #278 · apple/swift-crypto · GitHub, which has been standardised for JOSE as well, but no luck there either.
- Finally, a PR to replace Foundation with FoundationEssentials took well over a year to land Adopt FoundationEssentials instead of Foundation where available by t089 · Pull Request #317 · apple/swift-crypto · GitHub. It's in now, which is great, but this is a bad user experience.
It's a discouraging experience for any contributor, especially people from outside the ecosystem, who rightfully see an open source package and expect to be able to contribute a simple fix.
I think, as Swift matures on non-Apple platforms, the "rest" of the ecosystem needs a crypto package that's not constrained by CryptoKit. I'm sure there are good reasons for sharing code between CryptoKit and Swift Crypto, but in my opinion, today that's not the best thing for the Swift ecosystem. I think we as a community should be able to make PRs into a Crypto package if needed and to evolve it based on the needs of all the platforms Swift now supports, considering what's best for the package and the ecosystem and not having our hands tied by a closed source API.
One possible suggestion would be a Crypto package under swiftlang. This could start by simply forking SwiftCrypto and initially sharing SwiftCrypto's API, since that's what's currently used everywhere and would require minimal changes from users to adopt. In the long term however we would be able to update and change both the API and internals of the package however the ecosystem sees fit, just like a usual open source package works.
The other solution would be what was suggested in the original post: having SwiftCrypto drift away from CryptoKit. This has not happened and has not been discussed in the last two years, so I don't see it as particularly feasible.
This post is supposed to start a conversation about this and see what the consensus of the community is. I would really like to know what the other community member's experiences have been with Swift Crypto.