punchnet-macos/Tun/Punchnet/Cipher/CCChaCha20Cipher.swift
2026-03-17 16:19:51 +08:00

78 lines
2.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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 {
/// NonceServerRange + + 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)
// 40bit, id24
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
}
}
}