Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Kitura/BlueSSLService
SSL/TLS Add-in for BlueSocket using Secure Transport and OpenSSL
https://github.com/Kitura/BlueSSLService
linux macos networking security socket swift
Last synced: 5 days ago
JSON representation
SSL/TLS Add-in for BlueSocket using Secure Transport and OpenSSL
- Host: GitHub
- URL: https://github.com/Kitura/BlueSSLService
- Owner: Kitura
- License: apache-2.0
- Created: 2016-05-26T13:43:43.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2022-10-06T00:44:42.000Z (about 2 years ago)
- Last Synced: 2024-05-23T02:37:42.698Z (5 months ago)
- Topics: linux, macos, networking, security, socket, swift
- Language: Swift
- Homepage:
- Size: 373 KB
- Stars: 96
- Watchers: 30
- Forks: 48
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
- fucking-awesome-swift - BlueSSLService - SSL/TLS add-in for IBM's low level socket framework. (Libs / Network)
- awesome-swift - BlueSSLService - SSL/TLS Add-in for BlueSocket using Secure Transport and OpenSSL ` 📝 8 months ago` (Network [🔝](#readme))
- awesome-swift - BlueSSLService - SSL/TLS add-in for IBM's low level socket framework. (Libs / Network)
README
# BlueSSLService
SSL/TLS Add-in framework for [BlueSocket](https://github.com/Kitura/BlueSocket.git) in Swift using the Swift Package Manager. Works on supported Apple platforms (using Secure Transport) and on Linux (using OpenSSL).
## Prerequisites
### Swift
* Swift Open Source `swift-5.2-RELEASE` toolchain (**Minimum REQUIRED for latest release**)
* Swift Open Source `swift-5.5-RELEASE` toolchain (**Recommended**)
* Swift toolchain included in *Xcode Version 11.0 or higher*.BlueSSLService version 2.0 and above supports Swift 5.2+. See older versions of BlueSSLService for older versions of Swift.
### macOS
* macOS 10.14.6 (*Mojave*) or higher.
* Xcode Version 11.0 or higher using one of the above toolchains.
* Xcode Version 12.5 or higher using the included toolchain (*Recommended*).
* Secure Transport is provided by macOS.### iOS
* iOS 10.0 or higher
* Xcode Version 11.0 or higher using one of the above toolchains.
* Xcode Version 12.5 or higher using the included toolchain (*Recommended*).
* Secure Transport is provided by iOS.### Linux
* Ubuntu 16.04 (or 16.10 but only tested on 16.04) and 18.04.
* One of the Swift Open Source toolchain listed above.
* OpenSSL is provided by the distribution. **Note:** 3.0.x and later releases of OpenSSL are supported.
* The appropriate **libssl-dev** package is required to be installed when building.### Other Platforms
* **BlueSSLService** is **NOT** supported on *watchOS* since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
* **BlueSSLService** should work on *tvOS* but has **NOT** been tested.*Note:* See `Package.swift` for details.
## Build
To build `SSLService` from the command line:
```
% cd
% swift build
```## Testing
To run the supplied unit tests for **SSLService** from the command line:
```
% cd
% swift build
% swift test
```## Using BlueSSLService
### Before starting
The first you need to do is import both the `Socket` and `SSLService` frameworks. This is done by the following:
```swift
import Socket
import SSLService
```### Creating the Configuration
Both clients and server require at a minimum the following configuration items:
* CA Certficate (either `caCertificateFile` or `caCertificateDirPath`)
* Application certificate (`certificateFilePath`)
* Private Key file (`keyFilePath`)**or**
* Certificate Chain File (`chainFilePath`)
**or**, if using `self-signed` certificates:
* Application certificate (`certificateFilePath`)
* Private Key file (`keyFilePath`)**or**, if running on Linux (for now),
* A string containing a *PEM formatted* certificate
**or**, if running on macOS:
* Certificate Chain File (`chainFilePath`) in **PKCS12** format
**or**,
* No certificate at all.
**BlueSSLService** provides five ways to create a `Configuration` supporting the scenarios above. Only the **last version is supported on Apple platforms.** On Linux, **ALL** versions are supported. This is due to the limits imposed on the current implementation of *Apple Secure Transport*.
- `init()` - This API allows for the creation of *default* configuration. This is equivalent to calling the next initializer without changing any parameters.
- `init(withCipherSuite cipherSuite: String? = nil, clientAllowsSelfSignedCertificates: Bool = true)` - This API allows for the creation of configuration that does not contain a backing certificate or certificate chain. You can optionally provide a *cipherSuite* and decide whether to allow, when in client mode, use of *self-signed certificates* by the server.
- `init(withCACertificatePath caCertificateFilePath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)` - This API allows you to create a configuration using a self contained `Certificate Authority (CA)` file. The second parameter is the path to the `Certificate` file to be used by application to establish the connection. The next parameter is the path to the `Private Key` file used by application corresponding to the `Public Key` in the `Certificate`. If you're using `self-signed certificates`, set the last parameter to true.
- `init(withCACertificateDirectory caCertificateDirPath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)` - This API allows you to create a configuration using a directory of `Certificate Authority (CA)` files. These `CA` certificates **must** be hashed using the `Certificate Tool` provided by `OpenSSL`. The following parameters are identical to the previous API.
- `init(withPEMCertificateString certificateString: String, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)` - This API used when supplying a PEM formatted certificate presented as a *String*. **NOTE: At present, this API is only available on Linux.**
- `init(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, clientAllowsSelfSignedCertificates: Bool = false, cipherSuite: String? = nil)` - This API allows you to create a configuration using a single `Certificate Chain File` (see note 2 below). Add an optional password (if required) using the third parameter. Set the third parameter to true if the certificates you are using are `self-signed`, otherwise set it to false. If configuring a client and you want that client to be able to connect to servers using `self-signed` certificates, set the fourth parameter to true.*Note 1:* All `Certificate` and `Private Key` files must be `PEM` format. If supplying a certificate via a `String`, it must be PEM formatted.
*Note 2:* If using a certificate chain file, the certificates must be in `PEM` format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate `CA` certificates if applicable, and ending at the highest level (root) `CA`.
*Note 3:* For the first two versions of the API, if your `Private key` is included in your certificate file, you can omit this parameter and the API will use the same file name as specified for the certificate file.
*Note 4:* If you desire to customize the cipher suite used, you can do so by specifying the `cipherSuite` parameter when using one of the above initializers. If not specified, the default value is set to `DEFAULT` on Linux. On macOS, setting of this parameter is currently not supported and attempting to set it will result in unpredictable results. See the example below.
*Note 5:* If you're running on macOS, you must use the last form of `init` for the `Configuration` and provide a certificate chain file in `PKCS12` format, supplying a `password` if needed.
#### Example
The following illustrates creating a configuration (on *Linux*) using the second form of the API above using a self-signed certificate file as the key file and not supplying a certificate chain file. It also illustrates setting the cipher suite to `ALL` from the default:
```swift
import SSLService...
let myCertPath = "/opt/myApp/config/myCertificate.pem"
let myKeyPath = "/opt/myApp/config/myKeyFile.pem"let myConfig = SSLService.Configuration(withCACertificateDirectory: nil, usingCertificateFile: myCertPath, withKeyFile: myKeyFile)
myConfig.cipherSuite = "ALL"
...
```
*Note:* This example takes advantage of the `default` parameters available on the `SSLService.Configuration.init` function. Also, changing of the `cipher suite` on *macOS* is currently not supported.### Creating and using the SSLService
The following API is used to create the `SSLService`:
- `init?(usingConfiguration config: Configuration) throws` - This will create an instance of the `SSLService` using a previously created `Configuration`.Once the `SSLService` is created, it can applied to a previously created `Socket` instance that's just been created. This needs to be done **before** using the `Socket`. The following code snippet illustrates how to do this (again using *Linux*). *Note: Exception handling omitted for brevity.*
```swift
import Socket
import SSLService...
// Create the configuration...
let myCertPath = "/opt/myApp/config/myCertificate.pem"
let myKeyPath = "/opt/myApp/config/myKeyFile.pem"let myConfig = SSLService.Configuration(withCACertificateDirectory: nil, usingCertificateFile: myCertPath, withKeyFile: myKeyFile)
// Create the socket...
var socket = try Socket.create()
guard let socket = socket else {
fatalError("Could not create socket.")
}// Create and attach the SSLService to the socket...
// - Note: if you're going to be using the same
// configuration over and over, it'd be
// better to create it in the beginning
// as `let` constant.
socket.delegate = try SSLService(usingConfiguration: myConfig)// Start listening...
try socket.listen(on: 1337)```
The example above creates a `SSL server` socket. Replacing the `socket.listen` function with a `socket.connect` would result in an `SSL client` being created as illustrated below:
```
// Connect to the server...
try socket.connect(to: "someplace.org", port: 1337)
```
`SSLService` handles all the negotiation and setup for the secure transfer of data. The determining factor for whether or not a `Socket` is setup as a server or client `Socket` is API which is used to initiate a connection. `listen()` will cause the `Socket` to be setup as a server socket. Calling `connect()` results a client setup.### Extending Connection Verification
`SSLService` provides a callback mechanism should you need to specify **additional** verification logic. After creating the instance of `SSLService`, you can set the instance variable `verifyCallback`. This instance variable has the following signature:
```
public var verifyCallback: ((_ service: SSLService) -> (Bool, String?))? = nil
```
Setting this callback is not required. It defaults to `nil` unless set. The first parameter passed to your callback is the instance of `SSLService` that has this callback. This will allow you to access the public members of the `SSLService` instance in order to do additional verification. Upon completion, your callback should return a tuple. The first value is a `Bool` indicating the sucess or failure of the routine. The second value is an `optional String` value used to provide a description in the case where verification failed. In the event of callback failure, an `exception` will be thrown by the internal verification function. **Important Note:** To effectively use this callback requires knowledge of the platforms underlying secure transport service, `Apple Secure Transport` on `supported Apple platforms` and `OpenSSL` on `Linux`.### Skipping Connection Verification
If desired, `SSLService` can *skip* the connection verification. To accomplish this, set the property `skipVerification` to `true` after creating the `SSLService` instance. However, if the `verifyCallback` property (described above) is set, that callback will be called regardless of this setting. The default for property is false. It is **NOT** recommended that you skip the connection verification in a `production` environment unless you are providing verification via the `verificationCallback`.
## Community
We love to talk server-side Swift and Kitura. Join our [Slack](http://swift-at-ibm-slack.mybluemix.net/) to meet the team!
## License
This library is licensed under Apache 2.0. Full license text is available in [LICENSE](https://github.com/Kitura/BlueSSLService/blob/master/LICENSE).