// // 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? { // // let dictionary: [String: Any] = ["subscription": ["app_code":"com.imyfone.pdf", // "cdkey":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" // // let publicKeyString = Self.RsaPublic // // 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 // } // // //https://www.bejson.com/enc/rsa/网站生成的密钥要保留\r\n,去除前缀后缀 // //pem格式公钥 用途加密 //// public static let RsaPublic = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3U54ETmA3anGcL3D4uAa5vNI0S6rVoM\r\nCe9MhhP3MLRSW1gMaEHJE+vsVLN8ChFytkiI60CInYC91bk2x2FaurIIGEwowGz4lifDNsQFeWEd\r\nxs33U3fGM3+wGXC7sfYJrtmriqqmmM9eTqxvVWARD1EvnSUWseBRquCuSJ3rkQHxm0E9n88SAaM4\r\nopogLrAyz82NlWQSE55Yf0wiNNNh+HdiQOpTBIes5blBcxbai9KVQU5dqlkKNceg7rdDxANFlm49\r\nTn4yNkrS80w75IQL1xLzYfvWSlWn/falJR4jNBfBg7aTyJduGvWytTgphYVTPheJN/fEDRMR0XTV\r\nlnkHZQIDAQAB"; // public static let RsaPublic = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3U54ETmA3anGcL3D4uAa5vNI0S6rVoMCe9MhhP3MLRSW1gMaEHJE+vsVLN8ChFytkiI60CInYC91bk2x2FaurIIGEwowGz4lifDNsQFeWEdxs33U3fGM3+wGXC7sfYJrtmriqqmmM9eTqxvVWARD1EvnSUWseBRquCuSJ3rkQHxm0E9n88SAaM4opogLrAyz82NlWQSE55Yf0wiNNNh+HdiQOpTBIes5blBcxbai9KVQU5dqlkKNceg7rdDxANFlm49Tn4yNkrS80w75IQL1xLzYfvWSlWn/falJR4jNBfBg7aTyJduGvWytTgphYVTPheJN/fEDRMR0XTVlnkHZQIDAQAB"; // //pem格式私钥 用途解密 //// public static let RsaPrivate = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCHdTngROYDdqcZwvcPi4Brm80j\r\nRLqtWgwJ70yGE/cwtFJbWAxoQckT6+xUs3wKEXK2SIjrQIidgL3VuTbHYVq6sggYTCjAbPiWJ8M2\r\nxAV5YR3GzfdTd8Yzf7AZcLux9gmu2auKqqaYz15OrG9VYBEPUS+dJRax4FGq4K5IneuRAfGbQT2f\r\nzxIBoziimiAusDLPzY2VZBITnlh/TCI002H4d2JA6lMEh6zluUFzFtqL0pVBTl2qWQo1x6Dut0PE\r\nA0WWbj1OfjI2StLzTDvkhAvXEvNh+9ZKVaf99qUlHiM0F8GDtpPIl24a9bK1OCmFhVM+F4k398QN\r\nExHRdNWWeQdlAgMBAAECggEAA7uZQrLjW8kTRcR3pngDq/N5LbWhJ1HJ7yQnCbLXJwJxGo9MmDrn\r\n3aKsupDPpD9i198b1s/Kc/yuPouCFPB73ZU2X+UJYnQeTZT+7i1ssTGZ7naSkDxGu/iS08Cli3vq\r\nPGVHMuUM/j0IrkZWMxYYokFsfHofK/uwhHL4mouviClpCUoSy/OId0epVo81auFZLuAEK3/n9nG0\r\n9zRstRqOIxe4iRFEN45uj4+FZFBR5nDSRqztbVvdPJJip58IyN6ZRPbFJI9RUwzBl/WWvBJ6sXg1\r\n3SJAkvnJoO4q1ECbUL1kFELIEjWhsqM7QdGAaAYfUSYklVq6agwI9LL2Jk00wQKBgQDoPTW5hwqf\r\nlyA56hjZuHSgjOd3Tw8F3FrDanREc1GhZKrzVFmjC8s6o+dmKoRPnzjAJXtLtcJwEItJkkebZYA+\r\nWuY+y4c+oS+fp69UtgneqLn6knJHqZHhVG4wVzSUuLU0vnAeywHQZ7wE41V6coGwp0kb07N8kAWQ\r\nxTI64IafOQKBgQCVUSFVUNqAMToMTCF0qN7bp/AlFdfRMsZb+ANBDCv1pEL9IQpo+umBkTAgexOB\r\nLWuFO7B3+YIbE23HoDyR/IIodsbqemT3N0GqQ4HfSqe2Hlfuspqbx0T3UocSp2+2jEt4aHLrWlS1\r\nMUA24oEg0ybh6aotZF1CjyIOsY1T8Lj9jQKBgQDP/loKgjZyfgA/vjhpbfkN/YQkZ6r1vceQMtxU\r\nnc9jM2yjp0zsaNin+Tl6V+POB7Tk6ezF/tBYW4jT6G23cC1uKy0A2nmTDvs/CwhNXwfx4b1G/Dfb\r\nlLPxUhOpucB+3fp0dYanHXvPcciDvDLHCpy6YOhqQq0Ch15krSfycTpAiQKBgGmrnNdv/PIz5EzH\r\no/WXfQAefYkBSFa4hECZ6FOkdYfF09KoC2H4EECtq02RTGBi8HC9qUl+vmDDAzH/aF44QTS5ulQ+\r\ngi2iYUpJtCN+BeqQ1tIKe/g6scgGE6lT7W9XIiH4aTu+FayVSkiNS60bQa0nXFP7bzSnbwbPCKGa\r\n/pARAoGBAMbpl+vPULiJ4IrGbNQgA1hKNKhSerwBBKRsiM4MlcDVkjlpLd+bQ9POQy2y0r7GZQjW\r\nmt0XF3tb3Fp20U/ETUxKI4BktTX2A9hrmj5R3Uq+40KocQonjmIMEHF9GxnWF1YfzKtUD2DrDVp/\r\n1YMHv7Is7IVCtyIbLXVuMVXvGeab"; // public static let RsaPrivate = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCHdTngROYDdqcZwvcPi4Brm80jRLqtWgwJ70yGE/cwtFJbWAxoQckT6+xUs3wKEXK2SIjrQIidgL3VuTbHYVq6sggYTCjAbPiWJ8M2xAV5YR3GzfdTd8Yzf7AZcLux9gmu2auKqqaYz15OrG9VYBEPUS+dJRax4FGq4K5IneuRAfGbQT2fzxIBoziimiAusDLPzY2VZBITnlh/TCI002H4d2JA6lMEh6zluUFzFtqL0pVBTl2qWQo1x6Dut0PEA0WWbj1OfjI2StLzTDvkhAvXEvNh+9ZKVaf99qUlHiM0F8GDtpPIl24a9bK1OCmFhVM+F4k398QNExHRdNWWeQdlAgMBAAECggEAA7uZQrLjW8kTRcR3pngDq/N5LbWhJ1HJ7yQnCbLXJwJxGo9MmDrn3aKsupDPpD9i198b1s/Kc/yuPouCFPB73ZU2X+UJYnQeTZT+7i1ssTGZ7naSkDxGu/iS08Cli3vqPGVHMuUM/j0IrkZWMxYYokFsfHofK/uwhHL4mouviClpCUoSy/OId0epVo81auFZLuAEK3/n9nG09zRstRqOIxe4iRFEN45uj4+FZFBR5nDSRqztbVvdPJJip58IyN6ZRPbFJI9RUwzBl/WWvBJ6sXg13SJAkvnJoO4q1ECbUL1kFELIEjWhsqM7QdGAaAYfUSYklVq6agwI9LL2Jk00wQKBgQDoPTW5hwqflyA56hjZuHSgjOd3Tw8F3FrDanREc1GhZKrzVFmjC8s6o+dmKoRPnzjAJXtLtcJwEItJkkebZYA+WuY+y4c+oS+fp69UtgneqLn6knJHqZHhVG4wVzSUuLU0vnAeywHQZ7wE41V6coGwp0kb07N8kAWQxTI64IafOQKBgQCVUSFVUNqAMToMTCF0qN7bp/AlFdfRMsZb+ANBDCv1pEL9IQpo+umBkTAgexOBLWuFO7B3+YIbE23HoDyR/IIodsbqemT3N0GqQ4HfSqe2Hlfuspqbx0T3UocSp2+2jEt4aHLrWlS1MUA24oEg0ybh6aotZF1CjyIOsY1T8Lj9jQKBgQDP/loKgjZyfgA/vjhpbfkN/YQkZ6r1vceQMtxUnc9jM2yjp0zsaNin+Tl6V+POB7Tk6ezF/tBYW4jT6G23cC1uKy0A2nmTDvs/CwhNXwfx4b1G/DfblLPxUhOpucB+3fp0dYanHXvPcciDvDLHCpy6YOhqQq0Ch15krSfycTpAiQKBgGmrnNdv/PIz5EzHo/WXfQAefYkBSFa4hECZ6FOkdYfF09KoC2H4EECtq02RTGBi8HC9qUl+vmDDAzH/aF44QTS5ulQ+gi2iYUpJtCN+BeqQ1tIKe/g6scgGE6lT7W9XIiH4aTu+FayVSkiNS60bQa0nXFP7bzSnbwbPCKGa/pARAoGBAMbpl+vPULiJ4IrGbNQgA1hKNKhSerwBBKRsiM4MlcDVkjlpLd+bQ9POQy2y0r7GZQjWmt0XF3tb3Fp20U/ETUxKI4BktTX2A9hrmj5R3Uq+40KocQonjmIMEHF9GxnWF1YfzKtUD2DrDVp/1YMHv7Is7IVCtyIbLXVuMVXvGeab"; // // // func getPrivateKeyFromString(key: String) -> SecKey? { //// guard let data = key.data(using: .utf8) else { return nil } // guard let data = Data(base64Encoded: key) else { // return nil // } // // let parameters: [CFString: Any] = [ // kSecAttrKeyType: kSecAttrKeyTypeRSA, // kSecAttrKeyClass: kSecAttrKeyClassPrivate, // kSecAttrKeySizeInBits: 2048, // kSecReturnPersistentRef: true // ] // // var error: Unmanaged? // guard let privkeyData = Self.stripPrivateKeyHeader(data) else { // return nil // } // // if let privateKey = SecKeyCreateWithData(privkeyData as CFData, parameters as CFDictionary, &error) { // return privateKey // } else { // print("Error creating private key: \(error!.takeRetainedValue())") // return nil // } // } // // @objc public func decrypt(source: NSString) -> NSString? { // guard let data = Data(base64Encoded: source as String), data.isEmpty == false else { // KMPrint("需要解密的数据为空.") // return nil // } // guard let key = self.getPrivateKeyFromString(key: Self.RsaPrivate) else { // KMPrint("私钥生成失败.") // return nil // } // //// let data: Data = (NSData(base64Encoded: (source as String), options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)! as Data) //// let data = Data(base64Encoded: source as String) // if let deData = SecKeyCreateDecryptedData(key, .rsaEncryptionPKCS1, data as CFData, nil) { // return String(data: deData as Data, encoding: .utf8) as NSString? // } // return nil // } // // // Verify that the supplied key is in fact a PEM RSA private key key and strip the header // // On disk, a PEM RSA private key file starts with string "-----BEGIN RSA PRIVATE KEY-----", // // and ends with string "-----END RSA PRIVATE KEY-----" // static fileprivate func stripPrivateKeyHeader(_ privkey: Data) -> Data? { // if ( privkey.count == 0 ) { // return nil // } // // var keyAsArray = [UInt8](repeating: 0, count: privkey.count / MemoryLayout.size) // (privkey as NSData).getBytes(&keyAsArray, length: privkey.count) // // //magic byte at offset 22, check if it's actually ASN.1 // var idx = 22 // if ( keyAsArray[idx] != 0x04 ) { // return nil // } // idx += 1 // // //now we need to find out how long the key is, so we can extract the correct hunk // //of bytes from the buffer. // var len = Int(keyAsArray[idx]) // idx += 1 // let det = len & 0x80 //check if the high bit set // if (det == 0) { // //no? then the length of the key is a number that fits in one byte, (< 128) // len = len & 0x7f // } else { // //otherwise, the length of the key is a number that doesn't fit in one byte (> 127) // var byteCount = Int(len & 0x7f) // if (byteCount + idx > privkey.count) { // return nil // } // //so we need to snip off byteCount bytes from the front, and reverse their order // var accum: UInt = 0 // var idx2 = idx // idx += byteCount // while (byteCount > 0) { // //after each byte, we shove it over, accumulating the value into accum // accum = (accum << 8) + UInt(keyAsArray[idx2]) // idx2 += 1 // byteCount -= 1 // } // // now we have read all the bytes of the key length, and converted them to a number, // // which is the number of bytes in the actual key. we use this below to extract the // // key bytes and operate on them // len = Int(accum) // } // // //return privkey.subdata(in: idx..