项目中,使用了Https+RSA Sign的认证方式
实现方式为使用了Github开源库SecrecySwift,但此项目有一段时间没有人维护,按照readme中的集成方式,在新的Xcode9.4 or Swift4中不能在真机中正常运行。
修复方式如下:
Xcode 9.3, Swift 4项目, 引入此项目,按readme中的直接部署源码的方式已无法正常运行。
解决办法:
1.删除CommonCrypto文件夹,在项目 Targets 的 Build Settings 中 Import Paths 中删除 CommonCrypto, 在 Library Search Path 中删除 /usr/lib/system
2.在自己项目的xxx-Bridging-Header.h文件中,#import <CommonCrypto/CommonCrypto.h>
3.删除此项目中出现的import CommonCrypto,成功在真机上运行。
在发现此修复方式的过程中,尝试自己手写一套RSA Sign,参考如下代码:
let ts = Date().timeIntervalSince1970 * 1000000
let signString = "xxx&ts=\(Int64(ts))"
let pathPrivate = Bundle.main.path(forResource: "pri", ofType: "p12")
let pathPublic = Bundle.main.path(forResource: "pub", ofType: "der")
let privateUrl = URL(fileURLWithPath: pathPrivate!)
let privateData = try! Data(contentsOf: privateUrl)
let privatePwd = "xxx"
let options = [kSecImportExportPassphrase as String: privatePwd]
var rawItems: CFArray?
let status = SecPKCS12Import(privateData as CFData, options as CFDictionary, &rawItems)
guard status == errSecSuccess else { return }
let items = rawItems! as! Array<Dictionary<String, Any>>
let firstItem = items[0]
let identity = firstItem[kSecImportItemIdentity as String] as! SecIdentity?
var privateKey: SecKey?
let status1 = SecIdentityCopyPrivateKey(identity!, &privateKey)
guard status1 == errSecSuccess else { return }
var signedStr = ""
if #available(iOS 10.0, *) { // iOS10以后,系统原生实现方式
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA1
guard SecKeyIsAlgorithmSupported(privateKey!, .sign, algorithm) else {
return
}
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(privateKey!,
algorithm,
signString.data(using: .utf8)! as CFData,
&error) as Data? else {
return
}
signedStr = signature.base64EncodedString()
} else { // 老的实现方式,使用了SecrecySwift中的两个文件Digest.swift和SecrecyExtension.swift,在自己项目的xxx-Bridging-Header.h文件中,#import <CommonCrypto/CommonCrypto.h>,删除这两个文件中中出现的import CommonCrypto
let signData = signString.data(using: .utf8)!
let digestInputData = signData.digestData(.sha1)
guard digestInputData.count > 0 && digestInputData.count < SecKeyGetBlockSize(privateKey!) - 11 else {
return
}
let key_size = SecKeyGetBlockSize(privateKey!)
var sign_bytes = [UInt8](repeating: 0, count: key_size)
var sign_size : Int = key_size
let result = SecKeyRawSign(privateKey!, SecPadding.PKCS1SHA1, digestInputData.arrayOfBytes(), digestInputData.count, &sign_bytes, &sign_size)
guard result == errSecSuccess else {
return
}
let resultData = Data(bytes: UnsafePointer<UInt8>(sign_bytes), count: sign_size)
signedStr = resultData.base64EncodedString()
}