Transport Layer Security (TLS) is the successor to Secure Socket Layer 3.0 (SSL). SSL 3.0 was deprecated in June 2015. https://tools.ietf.org/html/rfc7568
A Swift wrapper for Transport Layer Security (TLS/SSL) using OpenSSL.
- Swifty Interface
- Client and Server
- Tested
The examples below assume you already have a socket library and you want to add TLS. If you do not already have a socket library, check out Socks by Honza Dvorsky.
There is an add-on for Socks called SecretSocks that includes this TLS library and provides a convenient makeSecret()
method for all Socks' sockets.
If you are using a different socket library, no need to worry. You only need access to the socket's file descriptor to use this package.
import TLS
let socket: MyUnsecureSocket
// Create an unsecure socket
// and grab its file descriptor.
// ...
let descriptor: Int32 = socket.mySocketDescriptor
Now that you have the descriptor, let's add TLS.
This adds a Transport Security Layer for interacting with a server from a client. No certificates are required to be a client.
let context = try TLS.Context(mode: .client, certificates: .none)
let secureSocket = try TLS.Socket(context: context, descriptor: descriptor)
try secureSocket.connect()
Here a context is created. You should hold on to this context if you intend to create multiple sockets. Your socket descriptor
is then used with the context
to create an TLS.Socket
.
The call to connect()
creates the connection to the server to start sending and receiving data. This should be called after the unsecure socket has called its version of connect()
.
This adds a Transport Security Layer for interacting with a client from a server. Setting up a server requires certificates.
let context = try TLS.Context(mode: .server, certificates: .files(
certificateFile: "./Certs/cert.pem",
privateKeyFile: "./Certs/key.pem",
signature: .selfSigned
))
let secureSocket = try TLS.Socket(context: context, descriptor: descriptor)
try secureSocket.accept()
Here a context is created. You should hold on to this context if you intend to create multiple sockets. Your socket descriptor
is then used with the context
to create an TLS.Socket
.
The call to accept()
accepts the connection and performs the TLS handshake with the client. This should be called after the unsecure socket has called its version of accept()
.
You can now send and receive data through the new secure socket.
try secureSocket.send([0x00, 0x01, 0x02])
let data = try secureSocket.receive(max: 3)
The Certificates
enum lets you supply the appropriate certificates for your TLS-enabled server.
public enum Certificates {
case none
case files(certificateFile: String, privateKeyFile: String, signature: Certificate.Signature)
case chain(chainFile: String, signature: Certificate.Signature)
}
public enum Certificate.Signature {
case selfSigned
case signedFile(caCertificateFile: String)
case signedDirectory(caCertificateDirectory: String)
}
You can verify the certificates presented by the peer manually.
try socket.verifyConnection()
The Error
enum comprises all errors that can be thrown from this module. The String
in all of the cases is a readable error message from OpenSSL.
public enum Error: ErrorProtocol {
case methodCreation
case contextCreation
case loadCACertificate(String)
case useCertificate(String)
case usePrivateKey(String)
case checkPrivateKey(String)
case useChain(String)
case socketCreation(String)
case file(String)
case accept(SocketError, String)
case connect(SocketError, String)
case send(SocketError, String)
case receive(SocketError, String)
case invalidPeerCertificate(PeerCertificateError)
}
Some cases of the Error
enum contain SocketError
s inside.
public enum SocketError: Int32, ErrorProtocol {
case none
case zeroReturn
case wantRead
case wantWrite
case wantConnect
case wantAccept
case wantX509Lookup
case syscall
case ssl
case unknown
}
One case of the Error
enum contains PeerCertificateError
s inside. This is thrown by verifyConnection()
.
public enum PeerCertificateError {
case notPresented
case noIssuerCertificate
case invalid
}
brew install openssl
brew link --force openssl
sudo apt-get install libssl-dev
Travis builds Swift TLS on both Ubuntu 14.04 and macOS 10.11. Check out the .travis.yml
file to see how this package is built and compiled during testing.
This wrapper was created to power Vapor, an Web Framework for Swift.
Created by Tanner Nelson.