I’m making an attempt to make https request in swift, with id created from certificates and key.
My code appear like this
To create the id.
func loadIdentity(certificates: String, privateKey: String)-> SecIdentity? {
guard let certData = Knowledge(base64Encoded: certificates, choices:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Unable to decode certificates PEM")
return nil
}
guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData as CFData) else {
return nil
}
let addCertQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecValueRef as String: cert,
kSecAttrLabel as String: "certificateLabel"]
let tag = "fedvfdvdf-tag".information(utilizing: .utf8)!
_ = deleteCertificateAndKey(certLabel: "certificateLabel",keyTag: tag )
let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
guard let pemKeyData = Knowledge(base64Encoded: privateKey, choices:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
return nil
}
let sizeInBits = pemKeyData.rely * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
kSecReturnPersistentRef: true
]
var error: Unmanaged?
guard let key = SecKeyCreateWithData(pemKeyData as CFData, keyDict as CFDictionary, &error) else {
return nil
}
let addKeyQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrIsPermanent as String: true,
kSecValueRef as String: key,
kSecAttrApplicationTag as String: tag
]
let privKeyAddStatus = SecItemAdd(addKeyQuery as CFDictionary, nil)
let getIdentityQuery = [
kSecClass : kSecClassIdentity,
kSecReturnData : true,
kSecReturnAttributes : true,
kSecReturnRef : true,
kSecMatchLimit : kSecMatchLimitAll
] as CFDictionary
var identityItem: CFTypeRef?
let standing = SecItemCopyMatching(getIdentityQuery , &identityItem)
print("identityItem completed with standing: (String(describing: identityItem))")
print("standing completed with standing: (standing)")
guard standing == errSecSuccess else {
print("Unable to create id")
return nil
}
return (identityItem as! SecIdentity);
}
to make api request
func makeAzureRequest(scopeId:String, registrationId:String, key:String, certificates:String, provisionHost:String, fileNameWithFolder:String, modelId:String, completion: @escaping (Outcome) -> Void ) throws {
guard let id = loadIdentity(certificates: certificates, privateKey: key) else {
throw NSError(area: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unable to create identity"])
}
let session = URLSession(configuration: .default, delegate: URLSessionPinningDelegate(id: id), delegateQueue: nil)
print("session: (session)")
guard let url = URL(string: "https://international.azure-devices-provisioning.web/(scopeId)/registrations/(registrationId)/register?api-version=2021-06-01") else {
throw NSError(area: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])
}
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("utility/json", forHTTPHeaderField: "Content material-Kind")
request.setValue("utf-8", forHTTPHeaderField: "Content material-Encoding")
let physique = ["registrationId": registrationId]
request.httpBody = attempt? JSONSerialization.information(withJSONObject: physique, choices: [])
let job = session.dataTask(with: request) { (information, response, error) in
if let error = error {
completion(.failure(error))
} else if let information = information, let responseString = String(information: information, encoding: .utf8) {
completion(.success(responseString))
}else {
completion(.failure(NSError(area: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred"])))
}
}
job.resume()
}
to name perform the place api perform is triggered.
@objc(AzureProvisionWithCertificate)
class AzureProvisionWithCertificate: NSObject {
@objc(provisionAndUploadFile:withRegistrationId:withKey:withCertificate:withProvisionHost:withFileNameWithFolder:withModelId:withResolver:withRejecter:)
func provisionAndUploadFile(scopeId:String, registrationId:String, key:String, certificates:String, provisionHost:String, fileNameWithFolder:String, modelId:String, resolve:@escaping RCTPromiseResolveBlock, reject:@escaping RCTPromiseRejectBlock) -> Void {
print("beginning swift code right here")
do {
attempt makeAzureRequest(scopeId: scopeId, registrationId:registrationId, key: key, certificates: certificates, provisionHost: provisionHost, fileNameWithFolder: fileNameWithFolder, modelId: modelId) { lead to
change outcome {
case .success(let responseString):
// Deal with success, maybe replace the UI or course of the response
case .failure(let error):
// Deal with failure, maybe present an error message to the consumer
}
}
} catch {
print("Didn't provoke request: (error.localizedDescription)")
}
}
}
And URLSessionPinningDelegate class appear like this to SSL pinning.
import Basis
import Safety
class URLSessionPinningDelegate: NSObject, URLSessionDelegate {
var id: SecIdentity
init(id: SecIdentity) {
self.id = id
}
func urlSession(_ session: URLSession,
didReceive problem: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if problem.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
let credential = URLCredential(id: self.id,
certificates: nil,
persistence: .forSession)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
Please assist.
Thanks in Advance!!!