KMVerificationRSA.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. //
  2. // KMVerificationRSA.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by Niehaoyu on 2024/8/9.
  6. //
  7. import Cocoa
  8. import CryptoKit
  9. import Security
  10. import CommonCrypto
  11. import Foundation
  12. @objc class KMVerificationRSA: NSObject {
  13. @objc func active(uniquesn: String, cdkey: String, model: String, os: String, language: String, appversion: String) -> String? {
  14. let dictionary: [String: Any] = ["subscription": ["app_code":"com.imyfone.pdf",
  15. "cdkey":cdkey],
  16. "device": ["unique_sn":uniquesn,
  17. "os":os,
  18. "platform":"DMG",
  19. "time_zone":"UTC",
  20. "language":language,
  21. "app_version":appversion]]
  22. if let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options:[]),
  23. let jsonString = String(data: jsonData, encoding: .utf8) {
  24. print(jsonString)
  25. if let publicKey = loadPublicKey() {
  26. let encryptedData = encrypt(plainText: jsonString, publicKey: publicKey)
  27. print("Encrypted data: \(encryptedData?.base64EncodedString() ?? "nil")")
  28. let encryptedString = encryptedData?.base64EncodedString();
  29. return encryptedString
  30. //Test
  31. // let dataToEncrypt = jsonString.data(using: .utf8)!
  32. //
  33. // if let encryptedDataChunks = encryptDataInChunks(data: dataToEncrypt, publicKey: publicKey) {
  34. // print("Encrypted data chunks:")
  35. // for chunk in encryptedDataChunks {
  36. // print(chunk.base64EncodedString()) // 输出每个加密块
  37. // }
  38. // print("111")
  39. // }
  40. //
  41. //
  42. // let message = jsonString
  43. // if let messageData = message.data(using: .utf8) {
  44. // if let publicKey = loadPublicKey() {
  45. // if let encryptedChunks = encrypt(data: messageData, publicKey: publicKey) {
  46. // let encryptedString = encryptedChunks.map { $0.base64EncodedString() }
  47. // print("Encrypted data: \(encryptedString)")
  48. // return encryptedString.first
  49. // }
  50. // }
  51. // }
  52. }
  53. }
  54. return nil
  55. }
  56. @objc func verify(uniquesn: String, model: String, os: String, language: String, appversion: String) -> String? {
  57. let dictionary: [String: Any] = ["subscription": ["app_code":"com.imyfone.pdf"],
  58. "device": ["unique_sn":uniquesn,
  59. "os":os,
  60. "platform":"DMG",
  61. "time_zone":"UTC",
  62. "language":language,
  63. "app_version":appversion]]
  64. if let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options:[]),
  65. let jsonString = String(data: jsonData, encoding: .utf8) {
  66. print(jsonString)
  67. if let publicKey = loadPublicKey() {
  68. let encryptedData = encrypt(plainText: jsonString, publicKey: publicKey)
  69. print("Encrypted data: \(encryptedData?.base64EncodedString() ?? "nil")")
  70. let encryptedString = encryptedData?.base64EncodedString();
  71. return encryptedString
  72. }
  73. //Test
  74. let message = jsonString
  75. if let messageData = message.data(using: .utf8) {
  76. if let publicKey = loadPublicKey() {
  77. if let encryptedChunks = encrypt(data: messageData, publicKey: publicKey) {
  78. let encryptedString = encryptedChunks.map { $0.base64EncodedString() }
  79. print("Encrypted data: \(encryptedString)")
  80. return encryptedString.first
  81. }
  82. }
  83. }
  84. }
  85. return nil
  86. }
  87. func encrypt(plainText: String, publicKey: SecKey) -> Data? {
  88. guard let data = plainText.data(using: .utf8) else {
  89. return nil
  90. }
  91. var error: Unmanaged<CFError>?
  92. let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error)
  93. if let error = error?.takeRetainedValue() {
  94. print("Error encrypting data: \(error)")
  95. return nil
  96. }
  97. return encryptedData as Data?
  98. }
  99. func encrypt(data: Data, publicKey: SecKey) -> [Data]? {
  100. let maxChunkSize = 214 // 对于 RSA-2048,214 是最大加密长度
  101. var chunks = [Data]()
  102. var offset = 0
  103. while offset < data.count {
  104. let chunkSize = min(maxChunkSize, data.count - offset)
  105. let chunk = data.subdata(in: offset..<offset + chunkSize)
  106. if let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, chunk as CFData, nil) {
  107. chunks.append(encryptedData as Data)
  108. } else {
  109. return nil // 加密失败
  110. }
  111. offset += chunkSize
  112. }
  113. return chunks
  114. }
  115. func loadPublicKey() -> SecKey? {
  116. // let publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqYKtu5pbT3bhbOfZ7XFhw1IEiqGvx/z3YwvcrLvG6I+EBbim/YuDfSTqpcTZSjbMeLz8nCzkAsMakoimzI6XpNQOZN35cDCFkjn0vicpnfla2JPMxREwddblAz7u/EMdx71ElcY+UYfSu1QM0Lepc2QPWw9oaD/cNktH6xE6eogLEH0k8ZYP8YIzTW02og7mNtLVO1ssKQYUCIQ5LkKA7zypQul5upajE51rq49vdCoA98y2zBRTMXGM7tpa2rbXQ9fDMn5heCLVCXCHNXDwBMxNhURm7fEfxZPwq7DUmH8EWKXCKKhu+GP0c/eom50FzMxfN2wpQSgNfyNQ7bBgwIDAQAB"
  117. let publicKeyString = Self.RsaPublic
  118. guard let data = Data(base64Encoded: publicKeyString) else {
  119. return nil
  120. }
  121. let options: [String: Any] = [
  122. kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
  123. kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
  124. kSecAttrKeySizeInBits as String: 4096
  125. ]
  126. var error: Unmanaged<CFError>?
  127. let publicKey = SecKeyCreateWithData(data as CFData, options as CFDictionary, &error)
  128. if let error = error?.takeRetainedValue() {
  129. print("Error loading public key: \(error)")
  130. return nil
  131. }
  132. return publicKey
  133. }
  134. func base64Encode(string: String) -> String? {
  135. // 将字符串转换为 Data
  136. guard let data = string.data(using: .utf8) else {
  137. print("Error converting string to Data.")
  138. return nil
  139. }
  140. // 使用 Data 的 base64EncodedString() 方法进行编码
  141. let base64String = data.base64EncodedString()
  142. return base64String
  143. }
  144. // RSA 分块加密
  145. func encryptDataInChunks(data: Data, publicKey: SecKey) -> [Data]? {
  146. let blockSize = SecKeyGetBlockSize(publicKey) - 11 // PKCS#1 v1.5 填充需要额外字节
  147. var encryptedChunks: [Data] = []
  148. var offset = 0
  149. while offset < data.count {
  150. let size = min(data.count - offset, blockSize) // 计算当前块大小
  151. let chunk = data.subdata(in: offset..<offset+size)
  152. var error: Unmanaged<CFError>?
  153. let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error)
  154. guard let successData = encryptedData else {
  155. if let error = error?.takeRetainedValue() {
  156. print("Encryption failed: \(error)")
  157. }
  158. return nil
  159. }
  160. encryptedChunks.append(successData as Data)
  161. offset += size
  162. }
  163. return encryptedChunks
  164. }
  165. func encrypt22(data: Data, publicKey: SecKey) -> [Data]? {
  166. let keySizeInBytes = 256 // 对于 RSA-2048,密钥大小为 256 字节
  167. let paddingSize = 11 // PKCS#1 填充大小
  168. let maxChunkSize = keySizeInBytes - paddingSize // 最大可加密数据大小
  169. var chunks = [Data]()
  170. var offset = 0
  171. while offset < data.count {
  172. let chunkSize = min(maxChunkSize, data.count - offset)
  173. let chunk = data.subdata(in: offset..<offset + chunkSize)
  174. var error: Unmanaged<CFError>?
  175. guard let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, chunk as CFData, &error) else {
  176. print("Encryption error: \(error!.takeRetainedValue() as Error)")
  177. return nil
  178. }
  179. chunks.append(encryptedData as Data)
  180. offset += chunkSize
  181. }
  182. return chunks
  183. }
  184. //https://www.bejson.com/enc/rsa/网站生成的密钥要保留\r\n,去除前缀后缀
  185. //pem格式公钥 用途加密
  186. // public static let RsaPublic = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3U54ETmA3anGcL3D4uAa5vNI0S6rVoM\r\nCe9MhhP3MLRSW1gMaEHJE+vsVLN8ChFytkiI60CInYC91bk2x2FaurIIGEwowGz4lifDNsQFeWEd\r\nxs33U3fGM3+wGXC7sfYJrtmriqqmmM9eTqxvVWARD1EvnSUWseBRquCuSJ3rkQHxm0E9n88SAaM4\r\nopogLrAyz82NlWQSE55Yf0wiNNNh+HdiQOpTBIes5blBcxbai9KVQU5dqlkKNceg7rdDxANFlm49\r\nTn4yNkrS80w75IQL1xLzYfvWSlWn/falJR4jNBfBg7aTyJduGvWytTgphYVTPheJN/fEDRMR0XTV\r\nlnkHZQIDAQAB";
  187. public static let RsaPublic = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3U54ETmA3anGcL3D4uAa5vNI0S6rVoMCe9MhhP3MLRSW1gMaEHJE+vsVLN8ChFytkiI60CInYC91bk2x2FaurIIGEwowGz4lifDNsQFeWEdxs33U3fGM3+wGXC7sfYJrtmriqqmmM9eTqxvVWARD1EvnSUWseBRquCuSJ3rkQHxm0E9n88SAaM4opogLrAyz82NlWQSE55Yf0wiNNNh+HdiQOpTBIes5blBcxbai9KVQU5dqlkKNceg7rdDxANFlm49Tn4yNkrS80w75IQL1xLzYfvWSlWn/falJR4jNBfBg7aTyJduGvWytTgphYVTPheJN/fEDRMR0XTVlnkHZQIDAQAB";
  188. //pem格式私钥 用途解密
  189. // 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";
  190. 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";
  191. func getPrivateKeyFromString(key: String) -> SecKey? {
  192. // guard let data = key.data(using: .utf8) else { return nil }
  193. guard let data = Data(base64Encoded: key) else {
  194. return nil
  195. }
  196. let parameters: [CFString: Any] = [
  197. kSecAttrKeyType: kSecAttrKeyTypeRSA,
  198. kSecAttrKeyClass: kSecAttrKeyClassPrivate,
  199. kSecAttrKeySizeInBits: 2048,
  200. kSecReturnPersistentRef: true
  201. ]
  202. var error: Unmanaged<CFError>?
  203. guard let privkeyData = Self.stripPrivateKeyHeader(data) else {
  204. return nil
  205. }
  206. if let privateKey = SecKeyCreateWithData(privkeyData as CFData, parameters as CFDictionary, &error) {
  207. return privateKey
  208. } else {
  209. print("Error creating private key: \(error!.takeRetainedValue())")
  210. return nil
  211. }
  212. }
  213. @objc public func decrypt(source: NSString) -> NSString? {
  214. guard let data = Data(base64Encoded: source as String), data.isEmpty == false else {
  215. KMPrint("需要解密的数据为空.")
  216. return nil
  217. }
  218. guard let key = self.getPrivateKeyFromString(key: Self.RsaPrivate) else {
  219. KMPrint("私钥生成失败.")
  220. return nil
  221. }
  222. // let data: Data = (NSData(base64Encoded: (source as String), options: NSData.Base64DecodingOptions.ignoreUnknownCharacters)! as Data)
  223. // let data = Data(base64Encoded: source as String)
  224. if let deData = SecKeyCreateDecryptedData(key, .rsaEncryptionPKCS1, data as CFData, nil) {
  225. return String(data: deData as Data, encoding: .utf8) as NSString?
  226. }
  227. return nil
  228. }
  229. // Verify that the supplied key is in fact a PEM RSA private key key and strip the header
  230. // On disk, a PEM RSA private key file starts with string "-----BEGIN RSA PRIVATE KEY-----",
  231. // and ends with string "-----END RSA PRIVATE KEY-----"
  232. static fileprivate func stripPrivateKeyHeader(_ privkey: Data) -> Data? {
  233. if ( privkey.count == 0 ) {
  234. return nil
  235. }
  236. var keyAsArray = [UInt8](repeating: 0, count: privkey.count / MemoryLayout<UInt8>.size)
  237. (privkey as NSData).getBytes(&keyAsArray, length: privkey.count)
  238. //magic byte at offset 22, check if it's actually ASN.1
  239. var idx = 22
  240. if ( keyAsArray[idx] != 0x04 ) {
  241. return nil
  242. }
  243. idx += 1
  244. //now we need to find out how long the key is, so we can extract the correct hunk
  245. //of bytes from the buffer.
  246. var len = Int(keyAsArray[idx])
  247. idx += 1
  248. let det = len & 0x80 //check if the high bit set
  249. if (det == 0) {
  250. //no? then the length of the key is a number that fits in one byte, (< 128)
  251. len = len & 0x7f
  252. } else {
  253. //otherwise, the length of the key is a number that doesn't fit in one byte (> 127)
  254. var byteCount = Int(len & 0x7f)
  255. if (byteCount + idx > privkey.count) {
  256. return nil
  257. }
  258. //so we need to snip off byteCount bytes from the front, and reverse their order
  259. var accum: UInt = 0
  260. var idx2 = idx
  261. idx += byteCount
  262. while (byteCount > 0) {
  263. //after each byte, we shove it over, accumulating the value into accum
  264. accum = (accum << 8) + UInt(keyAsArray[idx2])
  265. idx2 += 1
  266. byteCount -= 1
  267. }
  268. // now we have read all the bytes of the key length, and converted them to a number,
  269. // which is the number of bytes in the actual key. we use this below to extract the
  270. // key bytes and operate on them
  271. len = Int(accum)
  272. }
  273. //return privkey.subdata(in: idx..<len)
  274. //return privkey.subdata(in: NSMakeRange(idx, len))
  275. return privkey.subdata(in: NSMakeRange(idx, len).toRange()!)
  276. }
  277. }