add chacha20
This commit is contained in:
parent
cb33d81428
commit
8538e89f92
@ -31,10 +31,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
|
|
||||||
// 加密算法
|
// 加密算法
|
||||||
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
||||||
let aesChiper = CCAESChiper()
|
|
||||||
|
|
||||||
self.rootTask = Task {
|
self.rootTask = Task {
|
||||||
self.contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher, aesCipher: aesChiper)
|
self.contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher)
|
||||||
await self.contextActor?.start()
|
await self.contextActor?.start()
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
}
|
}
|
||||||
@ -79,52 +77,4 @@ extension PacketTunnelProvider {
|
|||||||
|
|
||||||
return interfaces.first {$0.name == "en0"}
|
return interfaces.first {$0.name == "en0"}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
struct CCRSACipher: RSACipher {
|
|
||||||
var pubKey: String
|
|
||||||
let privateKeyDER: Data
|
|
||||||
|
|
||||||
init(keySize: Int) throws {
|
|
||||||
let (privateKey, publicKey) = try Self.loadKeys(keySize: keySize)
|
|
||||||
let privKeyStr = SwKeyConvert.PrivateKey.derToPKCS1PEM(privateKey)
|
|
||||||
|
|
||||||
self.pubKey = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey)
|
|
||||||
self.privateKeyDER = try SwKeyConvert.PrivateKey.pemToPKCS1DER(privKeyStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func decode(data: Data) throws -> Data {
|
|
||||||
let tag = Data()
|
|
||||||
let (decryptedData, _) = try CC.RSA.decrypt(data, derKey: self.privateKeyDER, tag: tag, padding: .pkcs1, digest: .none)
|
|
||||||
|
|
||||||
return decryptedData
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func loadKeys(keySize: Int) throws -> (Data, Data) {
|
|
||||||
if let privateKey = UserDefaults.standard.data(forKey: "privateKey"),
|
|
||||||
let publicKey = UserDefaults.standard.data(forKey: "publicKey") {
|
|
||||||
|
|
||||||
return (privateKey, publicKey)
|
|
||||||
} else {
|
|
||||||
let (privateKey, publicKey) = try CC.RSA.generateKeyPair(keySize)
|
|
||||||
UserDefaults.standard.setValue(privateKey, forKey: "privateKey")
|
|
||||||
UserDefaults.standard.setValue(publicKey, forKey: "publicKey")
|
|
||||||
|
|
||||||
return (privateKey, publicKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CCAESChiper: AESCipher {
|
|
||||||
func decypt(aesKey: Data, data: Data) throws -> Data {
|
|
||||||
let ivData = Data(aesKey.prefix(16))
|
|
||||||
return try CC.crypt(.decrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: ivData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func encrypt(aesKey: Data, data: Data) throws -> Data {
|
|
||||||
let ivData = Data(aesKey.prefix(16))
|
|
||||||
|
|
||||||
return try CC.crypt(.encrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: ivData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
//
|
|
||||||
// AESCipher.swift
|
|
||||||
// sdlan
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2025/7/14.
|
|
||||||
//
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
public protocol AESCipher {
|
|
||||||
func decypt(aesKey: Data, data: Data) throws -> Data
|
|
||||||
|
|
||||||
func encrypt(aesKey: Data, data: Data) throws -> Data
|
|
||||||
}
|
|
||||||
@ -26,15 +26,13 @@ actor SDLContextActor {
|
|||||||
var natType: SDLNATProberActor.NatType = .blocked
|
var natType: SDLNATProberActor.NatType = .blocked
|
||||||
|
|
||||||
// AES加密,授权通过后,对象才会被创建
|
// AES加密,授权通过后,对象才会被创建
|
||||||
nonisolated let aesCipher: AESCipher
|
private var dataCipher: CCDataCipher?
|
||||||
|
|
||||||
// aes
|
|
||||||
private var aesKey: Data?
|
|
||||||
|
|
||||||
// session token
|
// session token
|
||||||
private var sessionToken: Data?
|
private var sessionToken: Data?
|
||||||
|
|
||||||
// rsa的相关配置, public_key是本地生成的
|
// rsa的相关配置, public_key是本地生成的
|
||||||
|
// 加密算法相关
|
||||||
nonisolated let rsaCipher: RSACipher
|
nonisolated let rsaCipher: RSACipher
|
||||||
|
|
||||||
// 依赖的变量
|
// 依赖的变量
|
||||||
@ -84,11 +82,10 @@ actor SDLContextActor {
|
|||||||
// 注册任务
|
// 注册任务
|
||||||
private var registerTask: Task<Void, Never>?
|
private var registerTask: Task<Void, Never>?
|
||||||
|
|
||||||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher, aesCipher: AESCipher) {
|
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
||||||
self.provider = provider
|
self.provider = provider
|
||||||
self.config = config
|
self.config = config
|
||||||
self.rsaCipher = rsaCipher
|
self.rsaCipher = rsaCipher
|
||||||
self.aesCipher = aesCipher
|
|
||||||
|
|
||||||
self.puncherActor = SDLPuncherActor()
|
self.puncherActor = SDLPuncherActor()
|
||||||
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
||||||
@ -392,10 +389,28 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async {
|
private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async {
|
||||||
// 需要对数据通过rsa的私钥解码
|
// 需要对数据通过rsa的私钥解码
|
||||||
self.aesKey = try! self.rsaCipher.decode(data: Data(registerSuperAck.aesKey))
|
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
|
||||||
|
SDLLogger.shared.log("[SDLContext] registerSuperAck invalid key", level: .error)
|
||||||
|
self.provider.cancelTunnelWithError(SDLError.invalidKey)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let algorithm = registerSuperAck.algorithm.lowercased()
|
||||||
|
let regionId = registerSuperAck.regionID
|
||||||
self.sessionToken = registerSuperAck.sessionToken
|
self.sessionToken = registerSuperAck.sessionToken
|
||||||
|
|
||||||
SDLLogger.shared.log("[SDLContext] get registerSuperAck, aes_key len: \(self.aesKey!.count)", level: .info)
|
switch algorithm {
|
||||||
|
case "aes":
|
||||||
|
self.dataCipher = CCAESChiper(key: key)
|
||||||
|
case "chacha20":
|
||||||
|
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
|
||||||
|
default:
|
||||||
|
SDLLogger.shared.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)", level: .error)
|
||||||
|
self.provider.cancelTunnelWithError(SDLError.unsupportedAlgorithm(algorithm: algorithm))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLLogger.shared.log("[SDLContext] get registerSuperAck, aes_key len: \(key.count)", level: .info)
|
||||||
// 服务器分配的tun网卡信息
|
// 服务器分配的tun网卡信息
|
||||||
do {
|
do {
|
||||||
try await self.setNetworkSettings(networkAddress: self.config.networkAddress, dnsServer: SDLDNSClient.Helper.dnsServer)
|
try await self.setNetworkSettings(networkAddress: self.config.networkAddress, dnsServer: SDLDNSClient.Helper.dnsServer)
|
||||||
@ -511,7 +526,7 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handleHoleData(data: SDLData) async throws {
|
private func handleHoleData(data: SDLData) async throws {
|
||||||
guard let aesKey = self.aesKey else {
|
guard let dataCipher = self.dataCipher else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +536,7 @@ actor SDLContextActor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let decyptedData = try? self.aesCipher.decypt(aesKey: aesKey, data: Data(data.data)) else {
|
guard let decyptedData = try? dataCipher.decrypt(cipherText: Data(data.data)) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,7 +698,7 @@ actor SDLContextActor {
|
|||||||
let networkAddr = self.config.networkAddress
|
let networkAddr = self.config.networkAddress
|
||||||
// 将数据封装层2层的数据包
|
// 将数据封装层2层的数据包
|
||||||
let layerPacket = LayerPacket(dstMac: dstMac, srcMac: networkAddr.mac, type: type, data: data)
|
let layerPacket = LayerPacket(dstMac: dstMac, srcMac: networkAddr.mac, type: type, data: data)
|
||||||
guard let udpHole = self.udpHole, let aesKey = self.aesKey, let encodedPacket = try? self.aesCipher.encrypt(aesKey: aesKey, data: layerPacket.marshal()) else {
|
guard let udpHole = self.udpHole, let dataCipher = self.dataCipher, let encodedPacket = try? dataCipher.encrypt(plainText: layerPacket.marshal()) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
Tun/Punchnet/Cipher/CCAESChiper.swift
Normal file
27
Tun/Punchnet/Cipher/CCAESChiper.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// CCAESChiper.swift
|
||||||
|
// punchnet
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2026/3/17.
|
||||||
|
//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct CCAESChiper: CCDataCipher {
|
||||||
|
private let aesKey: Data
|
||||||
|
|
||||||
|
init(key: Data) {
|
||||||
|
self.aesKey = key
|
||||||
|
}
|
||||||
|
|
||||||
|
func decrypt(cipherText: Data) throws -> Data {
|
||||||
|
let ivData = Data(aesKey.prefix(16))
|
||||||
|
return try CC.crypt(.decrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: cipherText, key: aesKey, iv: ivData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encrypt(plainText: Data) throws -> Data {
|
||||||
|
let ivData = Data(aesKey.prefix(16))
|
||||||
|
|
||||||
|
return try CC.crypt(.encrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: plainText, key: aesKey, iv: ivData)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
77
Tun/Punchnet/Cipher/CCChaCha20Cipher.swift
Normal file
77
Tun/Punchnet/Cipher/CCChaCha20Cipher.swift
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// NonceGenerator.swift
|
||||||
|
// punchnet
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2026/3/17.
|
||||||
|
//
|
||||||
|
import Foundation
|
||||||
|
import CryptoKit
|
||||||
|
|
||||||
|
/// ChaCha20-Poly1305 加解密示例
|
||||||
|
struct CCChaCha20Cipher: CCDataCipher {
|
||||||
|
private let key: SymmetricKey
|
||||||
|
private let nonceGenerator: NonceGenerator
|
||||||
|
|
||||||
|
init(regionId: UInt32, keyData: Data) {
|
||||||
|
self.key = SymmetricKey(data: keyData)
|
||||||
|
self.nonceGenerator = NonceGenerator(regionId: regionId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 加密
|
||||||
|
func encrypt(plainText: Data) throws -> Data {
|
||||||
|
let nonce = nonceGenerator.nextNonceData()
|
||||||
|
let sealedBox = try ChaChaPoly.seal(plainText, using: key, nonce: .init(data: nonce))
|
||||||
|
|
||||||
|
return sealedBox.combined
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 解密
|
||||||
|
func decrypt(cipherText: Data) throws -> Data {
|
||||||
|
let sealedBox = try ChaChaPoly.SealedBox(combined: cipherText)
|
||||||
|
return try ChaChaPoly.open(sealedBox, using: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CCChaCha20Cipher {
|
||||||
|
|
||||||
|
/// Nonce生成器(基于ServerRange + 毫秒时间低位 + 本地自增counter)
|
||||||
|
final class NonceGenerator {
|
||||||
|
private let locker = NSLock()
|
||||||
|
|
||||||
|
private let regionId: UInt32 // 32-bit 全局前缀
|
||||||
|
private var counter: UInt64 = 0 // 自增counter
|
||||||
|
|
||||||
|
init(regionId: UInt32) {
|
||||||
|
self.regionId = regionId
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 生成64-bit Nonce
|
||||||
|
func nextNonceData() -> Data {
|
||||||
|
locker.lock()
|
||||||
|
defer {
|
||||||
|
locker.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
let nowMillis = UInt64(Date().timeIntervalSince1970 * 1000)
|
||||||
|
// 时间占用40个bit位, 自增id占用24位
|
||||||
|
let timeMask: UInt64 = (1 << 40) - 1
|
||||||
|
let timeLow = nowMillis & timeMask
|
||||||
|
|
||||||
|
// 生成 Nonce
|
||||||
|
let counterMask: UInt64 = (1 << 24) - 1
|
||||||
|
let nonce = (timeLow << 24) | (counter & counterMask)
|
||||||
|
// 自增counter
|
||||||
|
self.counter = (self.counter + 1) & counterMask // 超过最大值回到0
|
||||||
|
|
||||||
|
var data = Data()
|
||||||
|
// region: UInt32 -> 4字节大端
|
||||||
|
data.append(contentsOf: withUnsafeBytes(of: regionId.bigEndian, Array.init))
|
||||||
|
// nonce: UInt64 -> 8字节大端
|
||||||
|
data.append(contentsOf: withUnsafeBytes(of: nonce.bigEndian, Array.init))
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
13
Tun/Punchnet/Cipher/CCDataCipher.swift
Normal file
13
Tun/Punchnet/Cipher/CCDataCipher.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// AESCipher.swift
|
||||||
|
// sdlan
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2025/7/14.
|
||||||
|
//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol CCDataCipher {
|
||||||
|
func decrypt(cipherText: Data) throws -> Data
|
||||||
|
|
||||||
|
func encrypt(plainText: Data) throws -> Data
|
||||||
|
}
|
||||||
41
Tun/Punchnet/Cipher/CCRSACipher.swift
Normal file
41
Tun/Punchnet/Cipher/CCRSACipher.swift
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// CCRSACipher.swift
|
||||||
|
// punchnet
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2026/3/17.
|
||||||
|
//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct CCRSACipher: RSACipher {
|
||||||
|
var pubKey: String
|
||||||
|
let privateKeyDER: Data
|
||||||
|
|
||||||
|
init(keySize: Int) throws {
|
||||||
|
let (privateKey, publicKey) = try Self.loadKeys(keySize: keySize)
|
||||||
|
let privKeyStr = SwKeyConvert.PrivateKey.derToPKCS1PEM(privateKey)
|
||||||
|
|
||||||
|
self.pubKey = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey)
|
||||||
|
self.privateKeyDER = try SwKeyConvert.PrivateKey.pemToPKCS1DER(privKeyStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func decode(data: Data) throws -> Data {
|
||||||
|
let tag = Data()
|
||||||
|
let (decryptedData, _) = try CC.RSA.decrypt(data, derKey: self.privateKeyDER, tag: tag, padding: .pkcs1, digest: .none)
|
||||||
|
|
||||||
|
return decryptedData
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func loadKeys(keySize: Int) throws -> (Data, Data) {
|
||||||
|
if let privateKey = UserDefaults.standard.data(forKey: "privateKey"),
|
||||||
|
let publicKey = UserDefaults.standard.data(forKey: "publicKey") {
|
||||||
|
|
||||||
|
return (privateKey, publicKey)
|
||||||
|
} else {
|
||||||
|
let (privateKey, publicKey) = try CC.RSA.generateKeyPair(keySize)
|
||||||
|
UserDefaults.standard.setValue(privateKey, forKey: "privateKey")
|
||||||
|
UserDefaults.standard.setValue(publicKey, forKey: "publicKey")
|
||||||
|
|
||||||
|
return (privateKey, publicKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,4 +8,7 @@
|
|||||||
enum SDLError: Error {
|
enum SDLError: Error {
|
||||||
case socketClosed
|
case socketClosed
|
||||||
case socketError
|
case socketError
|
||||||
|
|
||||||
|
case invalidKey
|
||||||
|
case unsupportedAlgorithm(algorithm: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -127,7 +127,13 @@ struct SDLRegisterSuperAck: @unchecked Sendable {
|
|||||||
|
|
||||||
var pktID: UInt32 = 0
|
var pktID: UInt32 = 0
|
||||||
|
|
||||||
var aesKey: Data = Data()
|
/// 目前支持aes, chacha20
|
||||||
|
var algorithm: String = String()
|
||||||
|
|
||||||
|
var key: Data = Data()
|
||||||
|
|
||||||
|
/// 逻辑分段,chacha20加密算法需要使用该字段
|
||||||
|
var regionID: UInt32 = 0
|
||||||
|
|
||||||
var sessionToken: Data = Data()
|
var sessionToken: Data = Data()
|
||||||
|
|
||||||
@ -268,7 +274,7 @@ struct SDLPolicyResponse: @unchecked Sendable {
|
|||||||
/// 版本号,客户端需要比较版本号确定是否覆盖; 请求端自己去管理版本号,服务端只是原样回写
|
/// 版本号,客户端需要比较版本号确定是否覆盖; 请求端自己去管理版本号,服务端只是原样回写
|
||||||
var version: UInt32 = 0
|
var version: UInt32 = 0
|
||||||
|
|
||||||
/// 4+1+2 的稀疏序列化规则
|
/// 1 + 2稀疏序列化规则, 按照: <<Proto:8, Port:16>> 这个格式序列号所有的规则信息; 下发的数据默认都是allow,deny规则的服务器端已经屏蔽
|
||||||
var rules: Data = Data()
|
var rules: Data = Data()
|
||||||
|
|
||||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
@ -725,8 +731,10 @@ extension SDLRegisterSuperAck: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl
|
|||||||
static let protoMessageName: String = "SDLRegisterSuperAck"
|
static let protoMessageName: String = "SDLRegisterSuperAck"
|
||||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
1: .standard(proto: "pkt_id"),
|
1: .standard(proto: "pkt_id"),
|
||||||
2: .standard(proto: "aes_key"),
|
2: .same(proto: "algorithm"),
|
||||||
3: .standard(proto: "session_token"),
|
3: .same(proto: "key"),
|
||||||
|
4: .standard(proto: "region_id"),
|
||||||
|
5: .standard(proto: "session_token"),
|
||||||
]
|
]
|
||||||
|
|
||||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
@ -736,8 +744,10 @@ extension SDLRegisterSuperAck: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl
|
|||||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
switch fieldNumber {
|
switch fieldNumber {
|
||||||
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.pktID) }()
|
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.pktID) }()
|
||||||
case 2: try { try decoder.decodeSingularBytesField(value: &self.aesKey) }()
|
case 2: try { try decoder.decodeSingularStringField(value: &self.algorithm) }()
|
||||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.sessionToken) }()
|
case 3: try { try decoder.decodeSingularBytesField(value: &self.key) }()
|
||||||
|
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.regionID) }()
|
||||||
|
case 5: try { try decoder.decodeSingularBytesField(value: &self.sessionToken) }()
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -747,18 +757,26 @@ extension SDLRegisterSuperAck: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl
|
|||||||
if self.pktID != 0 {
|
if self.pktID != 0 {
|
||||||
try visitor.visitSingularUInt32Field(value: self.pktID, fieldNumber: 1)
|
try visitor.visitSingularUInt32Field(value: self.pktID, fieldNumber: 1)
|
||||||
}
|
}
|
||||||
if !self.aesKey.isEmpty {
|
if !self.algorithm.isEmpty {
|
||||||
try visitor.visitSingularBytesField(value: self.aesKey, fieldNumber: 2)
|
try visitor.visitSingularStringField(value: self.algorithm, fieldNumber: 2)
|
||||||
|
}
|
||||||
|
if !self.key.isEmpty {
|
||||||
|
try visitor.visitSingularBytesField(value: self.key, fieldNumber: 3)
|
||||||
|
}
|
||||||
|
if self.regionID != 0 {
|
||||||
|
try visitor.visitSingularUInt32Field(value: self.regionID, fieldNumber: 4)
|
||||||
}
|
}
|
||||||
if !self.sessionToken.isEmpty {
|
if !self.sessionToken.isEmpty {
|
||||||
try visitor.visitSingularBytesField(value: self.sessionToken, fieldNumber: 3)
|
try visitor.visitSingularBytesField(value: self.sessionToken, fieldNumber: 5)
|
||||||
}
|
}
|
||||||
try unknownFields.traverse(visitor: &visitor)
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: SDLRegisterSuperAck, rhs: SDLRegisterSuperAck) -> Bool {
|
static func ==(lhs: SDLRegisterSuperAck, rhs: SDLRegisterSuperAck) -> Bool {
|
||||||
if lhs.pktID != rhs.pktID {return false}
|
if lhs.pktID != rhs.pktID {return false}
|
||||||
if lhs.aesKey != rhs.aesKey {return false}
|
if lhs.algorithm != rhs.algorithm {return false}
|
||||||
|
if lhs.key != rhs.key {return false}
|
||||||
|
if lhs.regionID != rhs.regionID {return false}
|
||||||
if lhs.sessionToken != rhs.sessionToken {return false}
|
if lhs.sessionToken != rhs.sessionToken {return false}
|
||||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
return true
|
return true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user