Home

Awesome

<p align="center"> <a href="https://www.kitura.io/packages.html#all"> <img src="https://img.shields.io/badge/docs-kitura.io-1FBCE4.svg" alt="APIDoc"> </a> <a href="https://travis-ci.org/Kitura/BlueSSLService"> <img src="https://travis-ci.org/Kitura/BlueSSLService.svg?branch=master" alt="Build Status - Master"> </a> <img src="https://img.shields.io/badge/os-macOS-green.svg?style=flat" alt="macOS"> <img src="https://img.shields.io/badge/os-iOS-green.svg?style=flat" alt="iOS"> <img src="https://img.shields.io/badge/os-linux-green.svg?style=flat" alt="Linux"> <img src="https://img.shields.io/badge/license-Apache2-blue.svg?style=flat" alt="Apache 2"> <a href="http://swift-at-ibm-slack.mybluemix.net/"> <img src="http://swift-at-ibm-slack.mybluemix.net/badge.svg" alt="Slack Status"> </a> </p>

BlueSSLService

SSL/TLS Add-in framework for BlueSocket in Swift using the Swift Package Manager. Works on supported Apple platforms (using Secure Transport) and on Linux (using OpenSSL).

Prerequisites

Swift

BlueSSLService version 2.0 and above supports Swift 5.2+. See older versions of BlueSSLService for older versions of Swift.

macOS

iOS

Linux

Other Platforms

Note: See Package.swift for details.

Build

To build SSLService from the command line:

% cd <path-to-clone>
% swift build

Testing

To run the supplied unit tests for SSLService from the command line:

% cd <path-to-clone>
% 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:

import Socket
import SSLService

Creating the Configuration

Both clients and server require at a minimum the following configuration items:

or

or, if using self-signed certificates:

or, if running on Linux (for now),

or, if running on macOS:

or,

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.

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:

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:

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.


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 to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.