https://github.com/fd-/sslsocketfactory-j2objc
An SSLSocketFactory for j2objc that uses the native iOS SecureTransport API
https://github.com/fd-/sslsocketfactory-j2objc
ios j2objc java ssl sslsocket swift tls
Last synced: about 2 months ago
JSON representation
An SSLSocketFactory for j2objc that uses the native iOS SecureTransport API
- Host: GitHub
- URL: https://github.com/fd-/sslsocketfactory-j2objc
- Owner: FD-
- License: apache-2.0
- Created: 2018-08-17T09:43:48.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2019-08-16T14:44:08.000Z (almost 7 years ago)
- Last Synced: 2025-02-26T15:46:10.935Z (over 1 year ago)
- Topics: ios, j2objc, java, ssl, sslsocket, swift, tls
- Language: Swift
- Homepage:
- Size: 22.5 KB
- Stars: 0
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Update
An Objective-C version based on my code is [now included in j2objc](https://github.com/google/j2objc/commit/2ad5fd094c1f7da14859cb57af76451fe4c7ec79), so this repository is mosty obsolete!
# SSLSocketFactory-j2objc
An SSLSocketFactory for j2objc that uses the native iOS [SecureTransport API](https://developer.apple.com/documentation/security/secure_transport). My implementation is in Swift, because I set up the j2objc-generated code as a static library that I use from within a Swift project. In that Swift project, I then create an `iOSSSLSocketFactory` that I pass to a function of the j2objc-generated code, where the original Java code uses it to create `SSLSockets`.
# Functionality
The provided `SSLSocketFactory` works, but it doesn't provide any customisability. The SecureTransport API's default values are used for any parameters. This means it works for the most common scenarios, for example when you have to use an `SSLSocket` for connecting to an HTTPS server.
I successfully use it with a slightly stripped-down version of [OkHttp that I ported](https://github.com/FD-/OkHttp-j2objc). In particular, as the required lower-level components are not bridged into the Java layer, I had to remove support for `HostnameVerifier`, and `CertificatePinner` (from OkHttp).
_Important_: Please be warned that the provided code produces memory leaks whenever it throws an Exception. AFAICT, this is because Swift wasn't really designed to deal with `NSExceptions`. My code uses Objective C utility functions so it is able to throw and catch exceptions, but there'll still be a Swift stack and I couldn't find any way to make Swift properly unwind the stack when throwing an exception (-fobjc-arc-exceptions doesn't seem to work for Swift). Instead of relying on the provided code in a production project, I rather suggest seeing it as a proof of concept for how a full-featured Objective C implementation could utilize the Secure Transport Framework.
# Overhead
Luckily, the iOS SecureTransport API is sufficiently low-level that it doesn't impose any specific threading pattern. This means that we only have a little overhead for creating an `IOSByteArray` when we need to call a function that doesn't accept a raw pointer. In particular, when reading from the underlying Socket, we have to create a new `IOSByteArray` to pass to the `Socket.getInputStream()`'s read function and later copy the data back into the native buffer.
# Possible Improvements
This implementation only includes rather basic error handling. Although error descriptions are included where available, any kind of error is thrown as an `IOException`, which means the Java layer cannot distinguish between different error causes.
For fully bridging SecureTransport's functionality into Java, the best approach would probably be to implement a Java SSLEngine on top of SecureTransport. The `SSLSocket` could then be reimplemented to use this engine. I think the [Conscrypt project](https://github.com/google/conscrypt) implemented a similar `SSLSocket`.
The SecureTransport API should provide all functionality that is needed. For implementing custom certificate handling (eg hostname verification, pinning), the native `SSLContext` can be set to break during the handshake by setting the corresponding option. I guess it's possible to retrieve the server's certificate from there, but I'm not sure how that certificate would be bridged into Java. That's as much as I've learned from putting together pieces of information I gathered online while implementing the basic `SSLSocketFactory`.
# Resources
Unfortunately, the official documentation for the SecureTransport API doesn't really provide much information. Luckily, there are a few open source projects that documented their findings while implementing support for the SecureTransport API. Some projects I found useful were:
- https://github.com/IBM-Swift/BlueSSLService
- VLC's SecureTransport code: https://github.com/videolan/vlc/blob/master/modules/misc/securetransport.c
- https://opensource.apple.com/source/Security/Security-55471/libsecurity_ssl/lib/SecureTransport.h.auto.html provides a mapping from error code numbers to short descriptions
- Chromium SecureTransport code (very entertaining documentation): https://github.com/adobe/chromium/blob/master/net/socket/ssl_client_socket_mac.cc