// // KMVerificationRSA.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/8/9. // import Cocoa import CryptoKit import Security import CommonCrypto import Foundation @objc class KMVerificationRSA: NSObject { @objc func active(uniquesn: String, cdkey: String, model: String, os: String, language: String, appversion: String) -> String? { var dictionary: [String: Any] = [:] if cdkey.isEmpty { dictionary = ["subscription": ["app_code":"com.imyfone.pdf"], "device": ["unique_sn":uniquesn, "os":os, "platform":"DMG", "time_zone":"UTC", "language":language, "app_version":appversion]] } else { dictionary = ["subscription": ["app_code":"com.imyfone.pdf", "email":cdkey], "device": ["unique_sn":uniquesn, "os":os, "platform":"DMG", "time_zone":"UTC", "language":language, "app_version":appversion]] } if let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options:[]), let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) if let publicKey = loadPublicKey() { let encryptedData = encrypt(plainText: jsonString, publicKey: publicKey) print("Encrypted data: \(encryptedData?.base64EncodedString() ?? "nil")") let encryptedString = encryptedData?.base64EncodedString(); return encryptedString //Test // let dataToEncrypt = jsonString.data(using: .utf8)! // // if let encryptedDataChunks = encryptDataInChunks(data: dataToEncrypt, publicKey: publicKey) { // print("Encrypted data chunks:") // for chunk in encryptedDataChunks { // print(chunk.base64EncodedString()) // 输出每个加密块 // } // print("111") // } // // // let message = jsonString // if let messageData = message.data(using: .utf8) { // if let publicKey = loadPublicKey() { // if let encryptedChunks = encrypt(data: messageData, publicKey: publicKey) { // let encryptedString = encryptedChunks.map { $0.base64EncodedString() } // print("Encrypted data: \(encryptedString)") // return encryptedString.first // } // } // } } } return nil } @objc func verify(uniquesn: String, model: String, os: String, language: String, appversion: String) -> String? { let dictionary: [String: Any] = ["subscription": ["app_code":"com.imyfone.pdf"], "device": ["unique_sn":uniquesn, "os":os, "platform":"DMG", "time_zone":"UTC", "language":language, "app_version":appversion]] if let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options:[]), let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) if let publicKey = loadPublicKey() { let encryptedData = encrypt(plainText: jsonString, publicKey: publicKey) print("Encrypted data: \(encryptedData?.base64EncodedString() ?? "nil")") let encryptedString = encryptedData?.base64EncodedString(); return encryptedString } //Test let message = jsonString if let messageData = message.data(using: .utf8) { if let publicKey = loadPublicKey() { if let encryptedChunks = encrypt(data: messageData, publicKey: publicKey) { let encryptedString = encryptedChunks.map { $0.base64EncodedString() } print("Encrypted data: \(encryptedString)") return encryptedString.first } } } } return nil } func encrypt(plainText: String, publicKey: SecKey) -> Data? { guard let data = plainText.data(using: .utf8) else { return nil } var error: Unmanaged? let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error) if let error = error?.takeRetainedValue() { print("Error encrypting data: \(error)") return nil } return encryptedData as Data? } func encrypt(data: Data, publicKey: SecKey) -> [Data]? { let maxChunkSize = 214 // 对于 RSA-2048,214 是最大加密长度 var chunks = [Data]() var offset = 0 while offset < data.count { let chunkSize = min(maxChunkSize, data.count - offset) let chunk = data.subdata(in: offset.. SecKey? { let publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqYKtu5pbT3bhbOfZ7XFhw1IEiqGvx/z3YwvcrLvG6I+EBbim/YuDfSTqpcTZSjbMeLz8nCzkAsMakoimzI6XpNQOZN35cDCFkjn0vicpnfla2JPMxREwddblAz7u/EMdx71ElcY+UYfSu1QM0Lepc2QPWw9oaD/cNktH6xE6eogLEH0k8ZYP8YIzTW02og7mNtLVO1ssKQYUCIQ5LkKA7zypQul5upajE51rq49vdCoA98y2zBRTMXGM7tpa2rbXQ9fDMn5heCLVCXCHNXDwBMxNhURm7fEfxZPwq7DUmH8EWKXCKKhu+GP0c/eom50FzMxfN2wpQSgNfyNQ7bBgwIDAQAB" guard let data = Data(base64Encoded: publicKeyString) else { return nil } let options: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeyClass as String: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits as String: 4096 ] var error: Unmanaged? let publicKey = SecKeyCreateWithData(data as CFData, options as CFDictionary, &error) if let error = error?.takeRetainedValue() { print("Error loading public key: \(error)") return nil } return publicKey } func base64Encode(string: String) -> String? { // 将字符串转换为 Data guard let data = string.data(using: .utf8) else { print("Error converting string to Data.") return nil } // 使用 Data 的 base64EncodedString() 方法进行编码 let base64String = data.base64EncodedString() return base64String } // RSA 分块加密 func encryptDataInChunks(data: Data, publicKey: SecKey) -> [Data]? { let blockSize = SecKeyGetBlockSize(publicKey) - 11 // PKCS#1 v1.5 填充需要额外字节 var encryptedChunks: [Data] = [] var offset = 0 while offset < data.count { let size = min(data.count - offset, blockSize) // 计算当前块大小 let chunk = data.subdata(in: offset..? let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error) guard let successData = encryptedData else { if let error = error?.takeRetainedValue() { print("Encryption failed: \(error)") } return nil } encryptedChunks.append(successData as Data) offset += size } return encryptedChunks } func encrypt22(data: Data, publicKey: SecKey) -> [Data]? { let keySizeInBytes = 256 // 对于 RSA-2048,密钥大小为 256 字节 let paddingSize = 11 // PKCS#1 填充大小 let maxChunkSize = keySizeInBytes - paddingSize // 最大可加密数据大小 var chunks = [Data]() var offset = 0 while offset < data.count { let chunkSize = min(maxChunkSize, data.count - offset) let chunk = data.subdata(in: offset..? guard let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, chunk as CFData, &error) else { print("Encryption error: \(error!.takeRetainedValue() as Error)") return nil } chunks.append(encryptedData as Data) offset += chunkSize } return chunks } }