用于 Swift 中 BlueSocket 的 SSL/TLS 插件框架,使用 Swift Package Manager。可在受支持的 Apple 平台(使用 Secure Transport)和 Linux(使用 OpenSSL)上运行。
swift-5.2-RELEASE
工具链(最新版本所需的最低版本)swift-5.5-RELEASE
工具链(推荐)BlueSSLService 2.0 及更高版本支持 Swift 5.2+。对于旧版本的 Swift,请参阅旧版本的 BlueSSLService。
注意:有关详细信息,请参见 Package.swift
。
要从命令行构建 SSLService
% cd <path-to-clone>
% swift build
要从命令行运行提供的 SSLService 单元测试
% cd <path-to-clone>
% swift build
% swift test
首先需要导入 Socket
和 SSLService
框架。这可以通过以下方式完成
import Socket
import SSLService
客户端和服务器至少需要以下配置项
caCertificateFile
或 caCertificateDirPath
)certificateFilePath
)keyFilePath
)或者
chainFilePath
)或者,如果使用 self-signed
证书
certificateFilePath
)keyFilePath
)或者,如果在 Linux 上运行(目前),
或者,如果在 macOS 上运行
chainFilePath
)或者,
BlueSSLService 提供了五种创建 Configuration
的方法,支持上述场景。 只有最后一个版本在 Apple 平台上受支持。 在 Linux 上,所有版本都受支持。 这是由于当前 Apple Secure Transport 实现的限制。
init()
- 此 API 允许创建默认配置。 这相当于调用下一个初始化程序而不更改任何参数。init(withCipherSuite cipherSuite: String? = nil, clientAllowsSelfSignedCertificates: Bool = true)
- 此 API 允许创建不包含支持证书或证书链的配置。 您可以选择提供一个 cipherSuite,并决定在客户端模式下是否允许服务器使用自签名证书。init(withCACertificatePath caCertificateFilePath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)
- 此 API 允许您使用包含的 证书颁发机构 (CA)
文件创建配置。 第二个参数是应用程序用来建立连接的 证书
文件的路径。 下一个参数是应用程序用于与 证书
中的 公钥
相对应的 私钥
文件的路径。 如果您使用的是 自签名证书
,请将最后一个参数设置为 true。init(withCACertificateDirectory caCertificateDirPath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)
- 此 API 允许您使用 证书颁发机构 (CA)
文件目录创建配置。 这些 CA
证书必须使用 OpenSSL
提供的 证书工具
进行哈希处理。 以下参数与先前的 API 相同。init(withPEMCertificateString certificateString: String, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil)
- 此 API 用于提供呈现为 String 的 PEM 格式的证书。 注意:目前,此 API 仅在 Linux 上可用。init(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, clientAllowsSelfSignedCertificates: Bool = false, cipherSuite: String? = nil)
- 此 API 允许您使用单个 证书链文件
创建配置(请参阅下面的注释 2)。 使用第三个参数添加可选密码(如果需要)。 如果您使用的证书是 自签名
的,请将第三个参数设置为 true,否则设置为 false。 如果配置客户端并且您希望该客户端能够使用 自签名
证书连接到服务器,请将第四个参数设置为 true。注意 1:所有 证书
和 私钥
文件必须是 PEM
格式。 如果通过 String
提供证书,则它必须是 PEM 格式。
注意 2:如果使用证书链文件,则证书必须是 PEM
格式,并且必须进行排序,从主题的证书(实际的客户端或服务器证书)开始,后跟中间 CA
证书(如果适用),并以最高级别(根)CA
结束。
注意 3:对于 API 的前两个版本,如果您的 私钥
包含在您的证书文件中,您可以省略此参数,并且 API 将使用为证书文件指定的相同文件名。
注意 4:如果您希望自定义使用的密码套件,可以通过在使用上述初始化程序之一时指定 cipherSuite
参数来实现。 如果未指定,则默认值在 Linux 上设置为 DEFAULT
。 在 macOS 上,目前不支持设置此参数,尝试设置它将导致不可预测的结果。 请参阅下面的示例。
注意 5:如果您在 macOS 上运行,则必须使用 Configuration
的最后一种 init
形式,并提供 PKCS12
格式的证书链文件,并在需要时提供 password
。
以下说明了如何使用上述 API 的第二种形式(在 Linux 上)创建配置,使用自签名证书文件作为密钥文件,而不提供证书链文件。 它还说明了如何将密码套件从默认值设置为 ALL
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"
...
注意:此示例利用了 SSLService.Configuration.init
函数上可用的 default
参数。 此外,目前不支持在 macOS 上更改 cipher suite
。
以下 API 用于创建 SSLService
init?(usingConfiguration config: Configuration) throws
- 这将使用先前创建的 Configuration
创建 SSLService
的实例。创建 SSLService
后,可以将其应用于先前创建的刚创建的 Socket
实例。 这需要在使用 Socket
之前完成。 以下代码片段说明了如何执行此操作(再次使用 Linux)。 注意:为简洁起见,省略了异常处理。
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)
上面的示例创建了一个 SSL server
套接字。 将 socket.listen
函数替换为 socket.connect
将导致创建一个 SSL client
,如下所示
// Connect to the server...
try socket.connect(to: "someplace.org", port: 1337)
SSLService
处理安全数据传输的所有协商和设置。 用于启动连接的 API 是确定 Socket
设置为服务器还是客户端 Socket
的决定性因素。 listen()
将导致 Socket
设置为服务器套接字。 调用 connect()
会导致客户端设置。
如果您需要指定额外的验证逻辑,SSLService
提供了一种回调机制。 创建 SSLService
的实例后,您可以设置实例变量 verifyCallback
。 此实例变量具有以下签名
public var verifyCallback: ((_ service: SSLService) -> (Bool, String?))? = nil
不需要设置此回调。 除非设置,否则默认为 nil
。 传递给您的回调的第一个参数是具有此回调的 SSLService
的实例。 这将允许您访问 SSLService
实例的公共成员,以便进行额外的验证。 完成后,您的回调应返回一个元组。 第一个值是一个 Bool
,指示例程的成功或失败。 第二个值是一个 optional String
值,用于在验证失败的情况下提供描述。 如果回调失败,内部验证函数将引发 exception
。 重要提示:要有效使用此回调,需要了解平台的基础安全传输服务,supported Apple platforms
上的 Apple Secure Transport
和 Linux
上的 OpenSSL
。
如果需要,SSLService
可以跳过连接验证。 为此,请在创建 SSLService
实例后将属性 skipVerification
设置为 true
。 但是,如果设置了 verifyCallback
属性(如上所述),则无论此设置如何,都将调用该回调。 该属性的默认值为 false。 不建议您在 production
环境中跳过连接验证,除非您通过 verificationCallback
提供验证。
我们喜欢讨论服务器端 Swift 和 Kitura。 加入我们的 Slack 来认识团队!
此库已获得 Apache 2.0 许可。 完整的许可证文本可在 LICENSE 中找到。