OpenSSL-Universal and the problem of OpenSSL on Apple platforms
OpenSSL package for SwiftPM, CocoaPod, and Carthage, multiplatform
At a glance
- What is it?
- OpenSSL-Universal packages OpenSSL for iOS, macOS, Catalyst, tvOS, visionOS and watchOS with precompiled static libraries, a framework and an XCFramework, distributed through Swift Package Manager, CocoaPods and Carthage. The reason it exists is a sentence from Apple, that OpenSSL has never provided a stable API from version to version and was never part of iOS.
- Who is it for?
- Adopt OpenSSL-Universal if your app has to link OpenSSL on an Apple platform and you would rather consume a prebuilt binary than run a full OpenSSL build for six SDKs. Do not adopt it if the platform's own crypto facilities cover what you need, and do not adopt it on the assumption that the binary is official OpenSSL, since the package is maintained by one developer and carries a custom licence.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why an app needs its own OpenSSL
The Why section of the README quotes Apple directly, and the quote is the reason the project exists. Although OpenSSL is commonly used in the open source community, OpenSSL does not provide a stable API from version to version. For this reason, although OS X provides OpenSSL libraries, the OpenSSL libraries in OS X are deprecated, and OpenSSL has never been provided as part of iOS.
That is a short summary of a real problem for cross platform developers. The server side of a system has a perfectly good OpenSSL. The iOS or watchOS side of the same product has nothing, because the platform never shipped one and the copy macOS used to provide is deprecated and going away. The options are to reimplement the cryptography with the platform's own frameworks, which changes the behaviour of the code and creates two implementations to test, or to build OpenSSL for the Apple targets yourself.
OpenSSL-Universal is the second option, pre-done. The package covers iOS, macOS, Catalyst, tvOS, visionOS and watchOS, and the description is that it is a complete solution to OpenSSL, coming with precompiled libraries and a script to build newer versions if necessary.
The audience is therefore narrow and clear: developers whose code links against OpenSSL, who ship to Apple platforms, and who would rather not maintain a cross compilation of OpenSSL for six SDKs themselves. The author is Marcin Krzyzanowski, and the project is funded through GitHub Sponsors, which is the arrangement that keeps a binary distribution project alive.
Three output shapes, and what each is for
The package produces three forms of the same library, and the choice between them is about how the consuming project consumes it.
The first is a static library pair, libcrypto.a and libssl.a, kept in the iphoneos/lib/ directory. The crypto library holds the primitives and the TLS implementation sits in ssl, which is the traditional OpenSSL split, and a static pair is what you want when the final binary has to be self contained and the symbols are not going to be shared with anything else.
The second is a framework, OpenSSL.framework, kept in the Frameworks/ directory. A framework is the unit Apple tooling understands best, with headers and resources in a bundle, and it is the shape an app target links against directly.
The third is an XCFramework, OpenSSL.xcframework, distributed as a zip from the releases page. The README explains what that is and links to the Apple documentation on distributing binary frameworks as Swift packages. An XCFramework is the format that lets one artefact hold several platform slices and architectures, which matters here because the library has to cover device and simulator variants for six platforms, and because the simulator and the device need different binaries.
The README's own recommendation is that a prebuilt framework is preferred in the Carthage case, and the general advice for anyone starting is to take the XCFramework, since it is the format that survives the platform matrix without a project file per destination.
The architecture matrix, per platform
The architectures section lists what is actually shipped, and it is worth reading line by line because the differences are not uniform.
For iOS the package has arm64 for the device and, for the simulator, both x86_64 and arm64. That second simulator slice matters more than it looks. The Apple Silicon simulator runs arm64, so a library built only for the x86_64 simulator either fails to link or runs under translation, and an app that only worked on Intel Macs becomes a problem for every developer on a modern laptop.
For macOS, x86_64 and arm64 are both included, and the arm64 slice also covers the Catalyst target. tvOS and visionOS ship arm64 only, which is the natural consequence of the device architectures. watchOS is the one with two slices, arm64 and arm64_32, the second an arm64 variant with 32-bit pointers.
The repository layout mirrors that matrix exactly, with a directory per destination: iphoneos/, iphonesimulator/, macosx/, macosx_catalyst/, appletvos/, appletvsimulator/, watchos/, watchsimulator/, visionos/ and visionsimulator/. A build system that has to produce a correct binary for each of those is a build system, and the Makefile and the Tuist based project configuration in the tree exist to drive it.
Building it yourself with make
The prebuilt binaries are the fast path, and the README is explicit that you do not have to use them. The build is three commands:
$ git clone https://github.com/krzyzanowskim/OpenSSL.git
$ cd OpenSSL
$ makeThe result of the build goes into the Frameworks/ directory, the same place the prebuilt framework lives, so the two paths produce the same artefact layout. The framing is that you can build it locally on your trusted machine, which is the argument for teams that do not want to consume an opaque binary from a release page but still do not want to hand-roll the cross compilation.
The Makefile at the root shows what the build has to keep straight. It pins the OpenSSL version as 3.6.5 and the marketing version as 3.6.5000, and it sets a deployment target per platform, iOS 12.0, macOS 10.15, visionOS 1.0, tvOS 12.0 and watchOS 8.0. It also has targets for build, frameworks, project, release, check-signing-identity, debug-signing and an all target that chains the checks, the project generation and the build.
The code signing part is the interesting bit. The Makefile shells out to the security command, filters for Apple Distribution identities, counts the unique identity names, and if exactly one is found it uses it automatically, extracting the team identifier from a name in the format Apple Distribution: Name (TEAMID) and failing the build with a clear error if the format is wrong. That is a build that tries to be unattended on a developer machine and loud on a release machine.
Swift Package Manager: take the binary package, not the source
The Swift Package Manager section carries a recommendation that saves a lot of time, and the reason is given in the sentence before it. The author advises using the OpenSSL-Package repository, which is a pure binary distribution of the very same binary, to avoid fetching the source repository, which is significant in size.
That is the whole point. The source repository carries the OpenSSL sources, the per platform build directories and the tooling, which is a clone large enough to matter in CI. The binary package carries the artefact and nothing else.
The dependency declaration looks like this:
dependencies: [
.package(url: "https://github.com/krzyzanowskim/OpenSSL-Package.git", from: "3.6.5000")
]And the consuming target then asks for the product by name:
.target(
name: "MyApp",
dependencies: [
.product(name: "OpenSSL", package: "OpenSSL-Package")
],
),The version in the from clause, 3.6.5000, matches the current release tag, and the naming convention is worth noticing. The versions are four digits, 3.6.5000 and earlier 3.6.3000 and 3.6.2000, and the 5000 suffix is the marketing version from the Makefile while 3.6.5 is the underlying OpenSSL release. The four digit scheme exists because Swift Package Manager needs a semantic version, and a patch level in the thousands lets the author ship a rebuilt OpenSSL for the same OpenSSL version without breaking the dependency rules.
CocoaPods and Carthage, and the binary only Carthage path
The two other package managers are handled in a few lines each.
For CocoaPods the podspec in the repository root, OpenSSL-Universal.podspec, is what you reference:
pod 'OpenSSL-Universal'For Carthage the situation is different, and the difference is informative. Carthage builds from source, which is exactly what this repository is not set up to do quickly, so the README says that using a prebuilt framework is preferred and gives a Cartfile entry that points at a JSON manifest:
binary "https://raw.githubusercontent.com/krzyzanowskim/OpenSSL/main/OpenSSL.json"The OpenSSL.json file at the root of the repository is the binary specification that tells Carthage where the prebuilt framework is, which is the modern Carthage way of shipping a binary dependency. The result is that Carthage users get the same artefact as everybody else, and the source build stays an option for the people who want it.
The Integration-Examples/ directory in the repository is there for the same reason, to show how each of the three package managers is wired into a project, which is the part that is genuinely fiddly and that a package README rarely gets right.
A custom licence and a four digit version scheme
The repository's licence is one GitHub cannot classify, with the terms in LICENSE.txt, and for a package that ships prebuilt binaries of a cryptographic library that is the first document to read. The obligations a redistribution licence places on the people who ship the framework inside an app are what determine whether you can use it commercially, and the badge does not answer that.
The maintenance picture is straightforward. The repository is not archived, the last push was on 2026-10-02, and the recent releases are OpenSSL 3.6.5000 on 2026-10-02, 3.6.3000 on 2026-07-30 and 3.6.2000 on 2026-05-21. Those are three releases between May and October, each carrying a new marketing version.
That pattern is the design in miniature. The OpenSSL version moves when OpenSSL moves, and the marketing version moves when the author rebuilds and republishes the binaries for a new set of platform slices or deployment targets. A team that pins 3.6.5000 gets a known artefact; a team that tracks the branch gets the newest rebuild.
The last thing worth noting is the practical advice in the FAQ about where the libraries can be used. The libraries work for iOS, macOS, appleTV, visionOS and watchOS, and the author pushes the question back at the reader, asking whether they are writing for old devices, new devices only, all iOS devices or only macOS, because the answer decides which deployment target you can set and therefore which slices of the package you need to vendor.
Editorial conclusion
Adopt OpenSSL-Universal if your app has to link OpenSSL on an Apple platform and you would rather consume a prebuilt binary than run a full OpenSSL build for six SDKs. Do not adopt it if the platform's own crypto facilities cover what you need, and do not adopt it on the assumption that the binary is official OpenSSL, since the package is maintained by one developer and carries a custom licence. Verify three things first: the deployment targets, because the build pins iOS 12, macOS 10.15, tvOS 12, watchOS 8 and visionOS 1.0, the architecture slice you need, since watchOS also ships an arm64_32 variant and the simulator slices differ from the device ones, and the licence in LICENSE.txt, which GitHub cannot classify. The last push was on 2026-10-02 and the newest release is OpenSSL 3.6.5000 from the same day.
Frequently asked questions
What is OpenSSL-Universal?
A package that provides OpenSSL for iOS, macOS, Catalyst, tvOS, visionOS and watchOS, distributed through CocoaPods, Carthage and Swift Package Manager. It ships precompiled libraries and includes a script to build newer versions if necessary.
Why does an Apple platform app need its own OpenSSL?
Apple's own documentation says OpenSSL does not provide a stable API from version to version, that the OpenSSL libraries in OS X are deprecated, and that OpenSSL has never been provided as part of iOS. The package exists to close that gap with prebuilt binaries for each Apple platform.
Which architectures does OpenSSL-Universal ship?
iOS with arm64 and a simulator build for x86_64 and arm64, macOS with x86_64 and arm64 including Catalyst, tvOS with arm64, visionOS with arm64, and watchOS with arm64 and arm64_32. Static libraries, a framework and an XCFramework are all produced.
How do I depend on OpenSSL-Universal from Swift Package Manager?
The README recommends the OpenSSL-Package repository, a pure binary distribution of the same binary that avoids fetching the large source repository, declared with .package(url: "https://github.com/krzyzanowskim/OpenSSL-Package.git", from: "3.6.5000") and consumed with .product(name: "OpenSSL", package: "OpenSSL-Package").
Can I build OpenSSL-Universal locally instead of using the prebuilt binaries?
Yes. Clone the repository, change into the OpenSSL directory and run make, and the result is placed in the Frameworks/ directory. The build pins OpenSSL 3.6.5 and per platform deployment targets of iOS 12.0, macOS 10.15, tvOS 12.0, watchOS 8.0 and visionOS 1.0.
What licence is OpenSSL-Universal released under?
A custom licence that GitHub cannot classify, with the terms in LICENSE.txt at the root of the repository, so the redistribution terms need to be read directly. The newest release is OpenSSL 3.6.5000 from 2026-10-02 and the last push was on 2026-10-02.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/krzyzanowskim-openssl)