tls 包

介绍

用于进行安全网络通信,提供启动 tls 服务器、连接 tls 服务器、发送数据、接收数据等功能。

使用本包需要外部依赖 OpenSSL 3sslcrypto 动态库文件,故使用前需安装相关工具:

  • 对于 Linux 操作系统,可参考以下方式:
    • 如果系统的包管理工具支持安装 OpenSSL 3 开发工具包,可通过这个方式安装,并确保系统安装目录下含有 libssl.solibssl.so.3libcrypto.solibcrypto.so.3 这些动态库文件,例如 Ubuntu 22.04 系统上可使用 sudo apt install libssl-dev 命令安装 libssl-dev 工具包;
    • 如果无法通过上面的方式安装,可自行下载 OpenSSL 3.x.x 源码编译安装软件包,并确保安装目录下含有 libssl.solibssl.so.3libcrypto.solibcrypto.so.3 这些动态库文件,然后可选择下面任意一种方式来保证系统链接器可以找到这些文件:
      • 在系统未安装 OpenSSL 的场景,安装时选择直接安装到系统路径下;
      • 安装在自定义目录的场景,将这些文件所在目录设置到环境变量 LD_LIBRARY_PATH 以及 LIBRARY_PATH 中。
  • 对于 Windows 操作系统,可按照以下步骤:
    • 自行下载 OpenSSL 3.x.x 源码编译安装 x64 架构软件包或者自行下载安装第三方预编译的供开发人员使用的 OpenSSL 3.x.x 软件包;
    • 确保安装目录下含有 libssl.dll.a(或 libssl.lib)、libssl-3-x64.dlllibcrypto.dll.a(或 libcrypto.lib)、libcrypto-3-x64.dll 这些库文件;
    • libssl.dll.a(或 libssl.lib)、libcrypto.dll.a(或 libcrypto.lib) 所在的目录路径设置到环境变量 LIBRARY_PATH 中,将 libssl-3-x64.dlllibcrypto-3-x64.dll 所在的目录路径设置到环境变量 PATH 中。
  • 对于 macOS 操作系统,可参考以下方式:
    • 使用 brew install openssl@3 安装,并确保系统安装目录下含有 libcrypto.dyliblibcrypto.3.dylib 这两个动态库文件;
    • 如果无法通过上面的方式安装,可自行下载 OpenSSL 3.x.x 源码编译安装软件包,并确保安装目录下含有 libcrypto.dyliblibcrypto.3.dylib 这两个动态库文件,然后可选择下面任意一种方式来保证系统链接器可以找到这些文件:
      • 在系统未安装 OpenSSL 的场景,安装时选择直接安装到系统路径下;
      • 安装在自定义目录的场景,将这些文件所在目录设置到环境变量 DYLD_LIBRARY_PATH 以及 LIBRARY_PATH 中。

如果未安装OpenSSL 3软件包或者安装低版本的软件包,程序可能无法使用并抛出相关异常 TlsException: Can not load openssl library or function xxx.

主要接口

struct CipherSuite

public struct CipherSuite <: ToString & Equatable<CipherSuite>

结构体 CipherSuite 为 TLS 中的密码套件。

prop allSupported

public static prop allSupported: Array<CipherSuite>

功能:返回所有支持的密码套件。

返回值:存放密码套件的数组

func toString

public func toString(): String

功能:返回密码套件名称。

返回值:密码套件名称

operator func ==

public operator func ==(that: CipherSuite): Bool

功能:判断两个密码套件是否相等。

参数:

  • that:被比较的密码套件对象

返回值:若相等,则返回 true;反之,返回 false

operator func !=

public operator func !=(that: CipherSuite): Bool

功能:判断两个密码套件是否不等。

参数:

  • that:被比较的密码套件对象

返回值:若不等,则返回 true;反之,返回 false

class TlsSocket

public class TlsSocket <: StreamingSocket & ToString & Equatable<TlsSocket> & Hashable

TlsSocket 用于在客户端及服务端间创建加密传输通道。

func client

public static func client(
    socket: StreamingSocket,
    session!: ?TlsSession = None,
    clientConfig!: TlsClientConfig = TlsClientConfig()
): TlsSocket

功能:根据传入的 StreamingSocket 实例创建指定地址的客户端 tls 套接字,该套接字可用于客户端 tls 握手及会话。

参数:

  • socket:已连接到服务端的客户端 tcp 套接字
  • session:TLS 会话 id,若存在可用的 TLS 会话, 则可通过该 id 恢复历史 TLS 会话,省去 TLS 建立连接时间,但使用该会话依然可能协商失败。默认为 None
  • clientConfig:客户端配置,默认为 TlsClientConfig()

返回值:Tls 套接字

func server

public static func server(
    socket: StreamingSocket,
    sessionContext!: ?TlsSessionContext = None,
    serverConfig!: TlsServerConfig
): TlsSocket

功能:根据传入的 StreamingSocket 实例创建指定地址的服务端 tls 套接字,该套接字可用于服务端 tls 握手及会话。

参数:

  • socket:TCP 连接建立完成后接受到套接字
  • sessionContext:TLS 会话 id, 若存在可用的 TLS 会话, 则可通过该 id 恢复历史 TLS 会话,省去 TLS 建立连接时间,但使用该会话依然可能协商失败。默认为 None
  • serverConfig:服务端配置,默认为 TlsServerConfig()

返回值:Tls 套接字。

prop socket

public prop socket: StreamingSocket

功能:TlsSocket 创建所使用的 StreamingSocket。

异常:

  • TlsException:本端配置为TLS的套接字已关闭时,抛出异常

prop readTimeout

public override mut prop readTimeout: ?Duration

功能:读写 TlsSocket 的读超时时间。

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:本端配置为TLS的套接字已关闭时,抛出异常
  • IllegalArgumentException:设定的读超时时间为负值时,抛出异常

prop writeTimeout

public override mut prop writeTimeout: ?Duration

功能:读写 TlsSocket 的写超时时间。

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:本端配置为TLS的套接字已关闭时,抛出异常
  • IllegalArgumentException:设定的写超时时间为负值时,抛出异常

prop localAddress

public override prop localAddress: SocketAddress

功能:读取 TlsSocket 的本地地址。

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:本端配置为TLS的套接字已关闭时,抛出异常

prop remoteAddress

public override prop remoteAddress: SocketAddress

功能:读取 TlsSocket 的远端地址。

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:本端配置为TLS的套接字已关闭时,抛出异常

prop alpnProtocolName

public prop alpnProtocolName: ?String

功能:读取协商到的应用层协议名称。

异常:

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常
  • IllegalMemoryException:内存申请失败时,抛出异常

prop tlsVersion

public prop tlsVersion: TlsVersion

功能:读取协商到的 TLS 版本。

异常:

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

prop session

public prop session: ?TlsSession

功能:读取 Tls 会话 id , 客户端会在握手成功后捕获当前会话的 id ,可使用该 id 重用该会话,省去 TLS 建立连接时间。连接建立未成功时,返回 None。

服务端不做捕获因此始终为 None。

异常:

  • TlsException:当套接字未完成TLS握手,抛出异常

prop domain

public prop domain: ?String

功能:读取协商到的服务端主机名称。

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

prop serverCertificate

public prop serverCertificate: Array<X509Certificate>

功能:服务器证书链由服务器提供或在服务器配置中预先配置。在服务端获取时为本端证书,在客户端获取时为对端证书。

这是可选的,因为服务器可能会跳过发送证书链。

这通常无效,但可以通过提供接受此类服务器的自定义 TLS 客户端配置来允许。

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

prop clientCertificate

public prop clientCertificate: ?Array<X509Certificate>

功能:客户端提供的客户端证书。在客户端获取时为本端证书,在服务端获取时为对端证书。

异常:

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

注意:当客户端会话恢复时,它可能会丢失。

prop peerCertificate

public prop peerCertificate: ?Array<X509Certificate>

功能:对端证书(如果对端提供)。

注意:在客户端获取时同 serverCertificate ,在服务端获取时同 clientCertificate。

异常:

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

prop cipherSuite

public prop cipherSuite: CipherSuite

功能:握手后协商到的加密套。

密码套件包含加密算法、用于消息认证的散列函数、密钥交换算法。

异常:

  • TlsException:当套接字未完成TLS握手或本端TLS套接字已关闭时,抛出异常

func handshake

public func handshake(timeout!: ?Duration = None): Unit

功能:TLS 握手。不支持重新协商握手,因此只能被调用一次。当调用对象可以为客户端或者服务端的 TlsSocket。

参数:

  • timeout:握手超时时间,默认为 None

异常:

  • SocketException:本端建连的底层 TCP 套接字关闭,抛出异常
  • SocketTimeoutException: 底层 TCP 套接字连接超时时,抛出异常
  • TlsException:当握手已经开始或者已经结束,抛出异常或当握手阶段出现系统错误时,抛出异常
  • IllegalArgumentException: 设定的握手超时时间为负值时,抛出异常

func read

public override func read(buffer: Array<Byte>): Int64

功能:TlsSocket 读取数据。

参数:

  • buffer:存储读取到的数据内容的容器

返回值:读取到的数据内容字节数

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:当 buffer 为空,或者 TlsSocket 未连接,或读取数据出现系统错误等

func write

public func write(buffer: Array<Byte>): Unit

功能:TlsSocket 发送数据。

参数:

  • buffer:存储将要发送的数据内容的容器

异常:

  • SocketException:本端建连的底层TCP套接字关闭,抛出异常
  • TlsException:当套接字已关闭,或者 TlsSocket 未连接,或写入数据出现系统错误等

func close

public func close(): Unit

功能:关闭套接字。

异常:

  • SocketException:底层连接无法关闭时,抛出异常

func isClosed

public func isClosed(): Bool

功能:返回套接字是否关闭的状态。

返回值:连接断开返回 true;否则,返回 false

func toString

public func toString(): String

功能:套接字状态。

返回值:该 tls 连接字符串

operator func ==

public override operator func ==(other: TlsSocket)

功能:套接字间判等。

参数:

  • other:对比的套接字

返回值:对比的套接字相同返回 true;否则,返回 false

operator func !=

public override operator func !=(other: TlsSocket)

功能:套接字间判不等。

参数:

  • other:对比的套接字

返回值:对比的套接字不同返回 true;否则,返回 false

func hashCode

public override func hashCode(): Int64

功能:返回 tls 套接字对象的哈希值。

返回值:对 tls 套接字对象进行哈希计算后得到的结果

enum TlsVersion

public enum TlsVersion <: ToString {
    | V1_2
    | V1_3
    | Unknown
}

TLS 协议版本

V1_2

V1_2

功能:表示 TLS 1.2。

V1_3

V1_3

功能:表示 V1_3。

Unknown

Unknown

功能:表示未知协议版本。

func toString

public override func toString(): String

功能:返回当前 TlsVersion 的字符串表示。

返回值:当前 TlsVersion 的字符串表示

enum CertificateVerifyMode

public enum CertificateVerifyMode {
    | Default
    | TrustAll
    | CustomCA(Array<X509Certificate>)
}

证书认证模式,TCP 连接建立成功后,客户端和服务端可交换证书,Default 模式使用系统证书。 在开发测试阶段,可使用 TrustAll 模式,该模式表示本端不作对对端证书的校验。此模式本端信任任意建立连接对象,一般仅在开发测试阶段使用。 CustomCA 模式可使用用户配置的证书地址,适用于用户证书无法设置为系统证书的场景。

Default

Default

功能:表示默认验证模式:根据系统CA验证证书。

TrustAll

TrustAll

功能:表示信任所有证书。

CustomCA

CustomCA(Array<X509Certificate>)

功能:表示根据提供的CA列表进行验证。

enum TlsClientIdentificationMode

public enum TlsClientIdentificationMode {
    | Disabled
    | Optional
    | Required
}

服务端对客户端证书的认证模式。

Disabled

Disabled

功能:表示服务端不校验客户端证书,客户端可以不发送证书和公钥,即单向认证。

Optional

Optional

功能:表示服务端校验客户端证书,但客户端可以不提供证书及公钥,不提供时则单向认证,提供时则为双向认证。

Required

Required

功能:表示服务端校验客户端证书,并且要求客户端必须提供证书和公钥,即双向认证。

enum HashType

public enum HashType <: ToString & Equatable<HashType> {
    | SHA512
    | SHA384
    | SHA256
    | SHA224
    | SHA1
}

功能:在签名前使用的 Hash 算法类型,参见 RFC5246 7.4.1.4.1。

SHA512

SHA512

功能:创建一个 SHA512 类型的枚举实例,表示签名前使用的 Hash 算法类型为 SHA512。

SHA384

SHA384

功能:创建一个 SHA384 类型的枚举实例,表示签名前使用的 Hash 算法类型为 SHA384。

SHA256

SHA256

功能:创建一个 SHA256 类型的枚举实例,表示签名前使用的 Hash 算法类型为 SHA256。

SHA224

SHA224

功能:创建一个 SHA224 类型的枚举实例,表示签名前使用的 Hash 算法类型为 SHA224。

SHA1

SHA1

功能:创建一个 SHA1 类型的枚举实例,表示签名前使用的 Hash 算法类型为 SHA1。

func toString

public func toString(): String

功能:转换为字符串。

返回值:转换后的字符串

operator func ==

public operator func ==(other: HashType): Bool

功能:判等。

参数:

  • other: 对比的签名前使用的 Hash 算法类型

返回值:相同返回 true;否则,返回 false

operator func !=

public operator func !=(other: HashType): Bool

功能:判不等。

参数:

  • other: 对比的签名前使用的 Hash 算法类型

返回值:不相同返回 true;否则,返回 false

enum SignatureType

public enum SignatureType <: ToString & Equatable<SignatureType> {
    | ECDSA
    | DSA
    | RSA
}

功能:签名算法类型,用于认证真实性。参见 RFC5246 7.4.1.4.1。

ECDSA

ECDSA

功能:创建一个 ECDSA 类型的枚举实例,表示采用椭圆曲线数字签名算法。

DSA

DSA

功能:创建一个 DSA 类型的枚举实例,表示采用数字签名算法。

RSA

RSA

功能:创建一个 RSA 类型的枚举实例,表示采用 RSA 加密算法。

func toString

public func toString(): String

功能:转换为字符串。

返回值:转换后的字符串

operator func ==

public operator func ==(other: SignatureType) : Bool

功能:判等。

参数:

  • other: 对比的签名算法类型

返回值:相同返回 true;否则,返回 false

operator func !=

public operator func !=(other: SignatureType) : Bool

功能:判不等。

参数:

  • other: 对比的签名算法类型

返回值:不相同返回 true;否则,返回 false

enum SignatureSchemeType

public enum SignatureSchemeType <: ToString & Equatable<SignatureSchemeType> {
    | RSA_PKCS1_SHA256
    | RSA_PKCS1_SHA384
    | RSA_PKCS1_SHA512
    | ECDSA_SECP256R1_SHA256
    | ECDSA_SECP384R1_SHA384
    | ECDSA_SECP521R1_SHA512
    | RSA_PSS_RSAE_SHA256
    | RSA_PSS_RSAE_SHA384
    | RSA_PSS_RSAE_SHA512
    | ED25519
    | ED448
    | RSA_PSS_PSS_SHA256
    | RSA_PSS_PSS_SHA384
    | RSA_PSS_PSS_SHA512
}

功能: 加密算法类型,用于保护网络通信的安全性和隐私性。

RSA_PKCS1_SHA256

RSA_PKCS1_SHA256

功能:创建一个 RSA_PKCS1_SHA256 类型的枚举实例,表示加密算法类型使用 RSA_PKCS1_SHA256。

RSA_PKCS1_SHA384

RSA_PKCS1_SHA384

功能:创建一个 RSA_PKCS1_SHA384 类型的枚举实例,表示加密算法类型使用 RSA_PKCS1_SHA384。

RSA_PKCS1_SHA512

RSA_PKCS1_SHA512

功能:创建一个 RSA_PKCS1_SHA512 类型的枚举实例,表示加密算法类型使用 RSA_PKCS1_SHA512。

ECDSA_SECP256R1_SHA256

ECDSA_SECP256R1_SHA256

功能:创建一个 ECDSA_SECP256R1_SHA256 类型的枚举实例,表示加密算法类型使用 ECDSA_SECP256R1_SHA256。

ECDSA_SECP384R1_SHA384

ECDSA_SECP384R1_SHA384

功能:创建一个 ECDSA_SECP384R1_SHA384 类型的枚举实例,表示加密算法类型使用 ECDSA_SECP384R1_SHA384。

ECDSA_SECP521R1_SHA512

ECDSA_SECP521R1_SHA512

功能:创建一个 ECDSA_SECP521R1_SHA512 类型的枚举实例,表示加密算法类型使用 ECDSA_SECP521R1_SHA512。

RSA_PSS_RSAE_SHA256

RSA_PSS_RSAE_SHA256

功能:创建一个 RSA_PSS_RSAE_SHA256 类型的枚举实例,表示加密算法类型使用 RSA_PSS_RSAE_SHA256。

RSA_PSS_RSAE_SHA384

RSA_PSS_RSAE_SHA384

功能:创建一个 RSA_PSS_RSAE_SHA384 类型的枚举实例,表示加密算法类型使用 RSA_PSS_RSAE_SHA384。

RSA_PSS_RSAE_SHA512

RSA_PSS_RSAE_SHA512

功能:创建一个 RSA_PSS_RSAE_SHA512 类型的枚举实例,表示加密算法类型使用 RSA_PSS_RSAE_SHA384。

ED25519

ED25519

功能:创建一个 ED25519 类型的枚举实例,表示加密算法类型使用 ED25519

ED448

ED448

功能:创建一个 ED448 类型的枚举实例,表示加密算法类型使用 ED448。

RSA_PSS_PSS_SHA256

RSA_PSS_PSS_SHA256

功能:创建一个 RSA_PSS_PSS_SHA256 类型的枚举实例,表示加密算法类型使用 RSA_PSS_PSS_SHA256。

RSA_PSS_PSS_SHA384

RSA_PSS_PSS_SHA384

功能:创建一个 RSA_PSS_PSS_SHA384 类型的枚举实例,表示加密算法类型使用 RSA_PSS_PSS_SHA384。

RSA_PSS_PSS_SHA512

RSA_PSS_PSS_SHA512

功能:创建一个 RSA_PSS_PSS_SHA512 类型的枚举实例,表示加密算法类型使用 RSA_PSS_PSS_SHA512。

func toString

public func toString(): String

功能:转换为字符串。

返回值:转换后的字符串

operator func ==

public operator func ==(other: SignatureSchemeType): Bool

功能:判等。

参数:

  • other: 对比的加密算法类型

返回值:相同返回 true;否则,返回 false

operator func !=

public operator func !=(other: SignatureSchemeType): Bool

功能:判不等。

参数:

  • other: 对比的加密算法类型

返回值:不相同返回 true;否则,返回 false

功能:哈希和签名算法列表。

enum SignatureAlgorithm

public enum SignatureAlgorithm <: ToString & Equatable<SignatureAlgorithm> {
    | SignatureAndHashAlgorithm(SignatureType, HashType)
    | SignatureScheme(SignatureSchemeType)
}

功能: 签名算法类型,签名算法用于确保传输数据的身份验证、完整性和真实性。

SignatureAndHashAlgorithm

SignatureAndHashAlgorithm(SignatureType, HashType)

功能:自 TLS 1.2 后出现,包含签名和哈希算法类型。

SignatureScheme

SignatureScheme(SignatureSchemeType)

功能:自 TLS 1.3 后出现,更为现代的指定签名算法的方式。

func toString

public func toString():String

功能:转换为字符串。

返回值:转换后的字符串

operator func ==

public operator func ==(other: SignatureAlgorithm) : Bool

功能:判等。

参数:

  • other: 对比的签名算法类型

返回值:相同返回 true;否则,返回 false

operator func !=

public operator func !=(other: SignatureAlgorithm) : Bool

功能:判不等。

参数:

  • other: 对比的签名算法类型

返回值:不相同返回 true;否则,返回 false

struct TlsClientConfig

public struct TlsClientConfig {
    public init()
    public var verifyMode: CertificateVerifyMode = CertificateVerifyMode.Default
}

客户端配置。

verifyMode

public var verifyMode: CertificateVerifyMode = CertificateVerifyMode.Default

功能:设置或获取证书认证模式,默认为 Default。

keylogCallback

public var keylogCallback: ?(TlsSocket, String) -> Unit = None

功能:握手过程的回调函数,提供 TLS 初始秘钥数据,用于调试和解密记录使用。

init

public init()

功能:构造 TlsClientConfig。

prop clientCertificate

public mut prop clientCertificate: ?(Array<X509Certificate>, PrivateKey)

功能:客户端证书和私钥。

prop domain

public mut prop domain: ?String

功能:读写要求的服务端主机地址 (SNI), None 表示不要求。

异常:

  • IllegalArgumentException:参数有 '\0' 字符时,抛出异常

prop alpnProtocolsList

public mut prop alpnProtocolsList: Array<String>

功能:要求的应用层协议名称。若列表为空,则客户将不协商应用层协议。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop cipherSuitesV1_2

public mut prop cipherSuitesV1_2: ?Array<String>

功能:基于 TLS 1.2 协议下的加密套。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop cipherSuitesV1_3

public mut prop cipherSuitesV1_3: ?Array<String>

功能:基于 TLS 1.3 协议下的加密套。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop minVersion

public mut prop minVersion: TlsVersion

功能:支持的 TLS 最小的版本。

注意:当仅设置 minVersion 而未设置 maxVersion ,或设置的 minVersion 高于 maxVersion ,将会在握手阶段抛出 TlsException。

prop maxVersion

public mut prop maxVersion: TlsVersion

功能:支持的 TLS 最大的版本。

注意:当仅设置 maxVersion 而未设置 minVersion ,或设置的 maxVersion 低于 minVersion ,将会在握手阶段抛出 TlsException。

prop signatureAlgorithms

public mut prop signatureAlgorithms: ?Array<SignatureAlgorithm>

功能:指定保序的签名和哈希算法。在值为 None 或者列表为空时,客户端会使用默认的列表。指定列表后,客户端可能不会发送不合适的签名算法。 参见 RFC5246 7.4.1.4.1.(TLS 1.2), RFC8446 4.2.3. (TLS 1.3)。

prop securityLevel

public mut prop securityLevel: Int32

功能:指定客户端的安全级别,默认值为2,可选参数值在 0-5 内,参数值含义参见 openssl-SSL_CTX_set_security_level 说明。

struct TlsServerConfig

public struct TlsServerConfig {
    public var verifyMode: CertificateVerifyMode = CertificateVerifyMode.Default
    public var clientIdentityRequired: TlsClientIdentificationMode = Disabled
    public init(certChain: Array<X509Certificate>, certKey: PrivateKey)
}

服务端配置

verifyMode

public var verifyMode: CertificateVerifyMode = CertificateVerifyMode.Default

功能:设置或获取认证模式,默认认证系统证书。

clientIdentityRequired

public var clientIdentityRequired: TlsClientIdentificationMode = Disabled

功能:设置或获取服务端要求客户端的认证模式,默认不要求客户端认证服务端证书,也不要求客户端发送本端证书。

keylogCallback

public var keylogCallback: ?(TlsSocket, String) -> Unit = None

功能:握手过程的回调函数,提供 TLS 初始秘钥数据,用于调试和解密记录使用。

init

public init(certChain: Array<X509Certificate>, certKey: PrivateKey)

功能:构造 TlsServerConfig 对象。

参数:

  • certChain:证书对象
  • certKey:私钥对象

prop serverCertificate

public mut prop serverCertificate: (Array<X509Certificate>, PrivateKey)

功能:服务端证书和对应的私钥文件。

prop supportedAlpnProtocols

public mut prop supportedAlpnProtocols: Array<String>

功能:应用层协商协议,若客户端尝试协商该协议,服务端将与选取其中相交的协议名称。若客户端未尝试协商协议,则该配置将被忽略。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop cipherSuitesV1_2

public mut prop cipherSuitesV1_2: Array<String>

功能:基于 TLS 1.2 协议下的加密套。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop cipherSuitesV1_3

public mut prop cipherSuitesV1_3: Array<String>

功能:基于 TLS 1.3 协议下的加密套。

异常:

  • IllegalArgumentException:列表元素有 '\0' 字符时,抛出异常

prop minVersion

public mut prop minVersion: TlsVersion

功能:支持的最小 TLS 版本。

注意:当仅设置 minVersion 而未设置 maxVersion ,或设置的 minVersion 高于 maxVersion ,将会在握手阶段抛出 TlsException。

prop maxVersion

public mut prop maxVersion: TlsVersion

功能:支持的最大 TLS 版本。

注意:当仅设置 maxVersion 而未设置 minVersion ,或设置的 maxVersion 低于 minVersion ,将会在握手阶段抛出 TlsException。

prop securityLevel

public mut prop securityLevel: Int32

功能:指定服务端的安全级别,默认值为2,可选参数值在 0-5 内,参数值含义参见 openssl-SSL_CTX_set_security_level 说明。

异常:

  • IllegalArgumentException: 当配置值不在 0-5 范围内时,抛出异常

prop dhParameters

public mut prop dhParameters: ?DHParamters

功能:指定服务端的 DH 密钥参数,默认为 None, 默认情况下使用 openssl 自动生成的参数值。

struct TlsSession

public struct TlsSession <: Equatable<TlsSession> & ToString & Hashable

当客户端 TLS 握手成功后,将会生成一个会话,当连接因一些原因丢失后,客户端可以通过这个会话 id 复用此次会话,省略握手流程。

此结构体表示已建立的客户端会话。此结构体实例用户不可创建,其内部结构对用户不可见。

operator func ==

public override operator func ==(other: TlsSession)

功能:判等。

参数:

  • other:被比较的会话对象

返回值:若会话对象相同,返回 true;否则,返回 false

operator func !=

public override operator func !=(other: TlsSession)

功能:判不等。

参数:

  • other:被比较的会话对象

返回值:若会话对象不同,返回 true;否则,返回 false

func toString

public override func toString(): String

功能:生成会话 id 字符串。

返回值:TlsSession(会话 id 字符串)

func hashCode

public override func hashCode(): Int64

功能:生成会话 id 哈希值。

返回值:会话 id 哈希值

class TlsSessionContext

public class TlsSessionContext <: Equatable<TlsSessionContext> & ToString

当客户端尝试恢复会话时,双方都必须确保他们正在恢复与合法对端的会话。TlsSessionContext 会做以下两件事情: 1. 验证客户端。 2. 给客户端提供信息,确保客户端所连接的服务端仍为相同实例。

func fromName

public static func fromName(name: String): TlsSessionContext

功能:通过 TlsSessionContext 保存的名称获取 TlsSessionContext 对象该名称用于区分 TLS 服务器,因此客户端依赖此名称来避免意外尝试恢复与错误的服务器的连接这里不一定使用加密安全名称,因为底层实现可以完成这项工作从此函数返回的具有相同名称的两个会话上下文可能不相等,并且不保证可替换,尽管它们是从相同的名称创建的因此,服务器实例应该在整个生命周期内创建一个会话上下文,并且在每次 TlsSocket.server() 调用中使用它。

参数:

  • name:会话上下文名称

返回值:会话上下文

operator func ==

public override operator func ==(other: TlsSessionContext)

功能:判等。

参数:

  • other:被比较的会话上下文对象

返回值:若 TlsSessionContext 对象相同,返回 true;否则,返回 false

operator func !=

public override operator func !=(other: TlsSessionContext)

功能:判不等。

参数:

  • other:被比较的会话上下文对象

返回值:若 TlsSessionContext 对象不同,返回 true;否则,返回 false

func toString

public override func toString(): String

功能:生成会话上下文名称字符串。

返回值:TlsSessionContext(会话上下文名称字符串)

class TlsException

public class TlsException <: Exception {
    public init()
    public init(message: String)
}

TLS 处理出现错误时抛出的异常

init

public init()

功能:构造异常。

init

public init(message: String)

功能:构造异常。

参数:

  • message:异常信息

示例

客户端示例

from std import fs.*, socket.*
from net import tls.*
from crypto import x509.{X509Certificate,PrivateKey}

main() {
    var config = TlsClientConfig()
    config.verifyMode = TrustAll
    config.alpnProtocolsList = ["h2"]

    // 用于恢复会话
    var lastSession: ?TlsSession = None
    
    while (true) { // 重新连接环路
        try (socket = TcpSocket("127.0.0.1", 8443)) {
            socket.connect() // 首先进行 TCP 连接
            try (tls = TlsSocket.client(socket, clientConfig: config, session: lastSession)) {
                try {
                    tls.handshake()  // then we are negotiating TLS
                    lastSession = tls.session // 如果成功协商下一次重新连接,将记住会话
                } catch (e: Exception) {
                    lastSession = None   // 如果协商失败,将删除会话
                    throw e
                }
    
               // tls实例已完成
               tls.write("Hello, peer! Let's discuss our personal secrets.\n".toArray())
            }
        } catch (e: Exception) {
            println("client connection failed ${e}, retrying...")
        }
    }
}

服务端示例

from std import fs.*, socket.*
from net import tls.*
from crypto import x509.{X509Certificate,PrivateKey}

let certificatePath = "./files/apiserver.crt"
let certificateKeyPath = "./files/apiserver.key"

main() {
    // 对证书以及私钥进行解析
    let pem = readTextFromFile(certificatePath)
    let keyText = readTextFromFile(certificateKeyPath)

    let certificate = X509Certificate.decodeFromPem(pem)
    let privateKey = PrivateKey.decodeFromPem(keyText)

    let config = TlsServerConfig(certificate, privateKey)

    //可选:允许恢复TLS会话
    let sessions= TlsSessionContext.fromName("my-server")
    
    try (server = TcpServerSocket(bindAt:8443)) {
        server.bind()
        
        server.acceptLoop { clientSocket =>
            try (tls = TlsSocket.server(clientSocket, serverConfig: config, sessionContext: sessions)) {
                tls.handshake()
                let buffer = Array<Byte>(100, item: 0)
                tls.read(buffer)
                println(buffer) // operate received data.
            }
        }
    }
}

// 简化示例代码的辅助函数
extend TcpServerSocket {
    func acceptLoop(handler: (TcpSocket) -> Unit) {
        while (true) {
            let client = accept()
            spawn {
                try {
                    handler(client)
                } finally {
                    client.close()
                }
            }
        }
    }
}

func readTextFromFile(path: String): String {
    var str = ""
    try (file = File(path, OpenOption.Open(true, false))) {
        str = String.fromUtf8(file.readToEnd())
    }
    str
}

证书热更新

from std import fs.*, socket.*
from net import tls.*
from crypto import x509.{X509Certificate,PrivateKey}

class MyServer {
    private var currentConfig: TlsServerConfig

    init(initialConfig: TlsServerConfig) { currentConfig = initialConfig }

    /**
      * 更改带有密钥的证书只会影响新的连接
      */
    public mut prop certificate: (Array<X509Certificate>, PrivateKey) {
        get() { currentConfig.serverCertificate }
        set(newCertificate) { currentConfig.serverCertificate = newCertificate }
    }

    public func onAcceptedConnection(client: StreamingSocket) {
        try (tls = TlsSocket.server(client, serverConfig: currentConfig)) {
            tls.handshake()
        }
    }
}

服务端证书及公钥在一份文件中

from std import fs.*, socket.*, collection.*
from net import tls.*
from crypto import x509.{X509Certificate,PrivateKey, Pem, PemEntry,DerBlob}

let certificatePath = "/etc/myserver/cert-and-key.pem"


func parsePem(text: String): (Array<X509Certificate>, PrivateKey) {
    let pem = Pem.decode(text)
    let chain = pem |>
        filter<PemEntry> { entry => entry.label == PemEntry.LABEL_CERTIFICATE } |>
        map<PemEntry, X509Certificate> { entry => X509Certificate.decodeFromDer(entry.body ?? DerBlob()) } |>
        collectArray

    let key = (pem |>
        filter<PemEntry> { entry => entry.label == PemEntry.LABEL_PRIVATE_KEY} |>
        map<PemEntry, PrivateKey> { entry => PrivateKey.decodeDer(entry.body ?? DerBlob()) } |>
        first) ?? throw Exception("No private key found in the PEM file")

    if (chain.isEmpty()) {
        throw Exception("No certificates found in the PEM file")
    }

    return (chain, key)
}

func readTextFromFile(path: String): String {
    var fileString = ""
    try (file = File(path, OpenOption.Open(true, false))) {
        fileString = String.fromUtf8(file.readToEnd())
        ()
    }
    fileString
}

main() {
    // 对证书及私钥进行解析
    let pem = readTextFromFile(certificatePath)

    let (certificate, privateKey) = parsePem(pem)

    var _ = TlsServerConfig(certificate, privateKey)

    // 进行https服务,请参阅其他服务器示例
}