I am trying to connect to MQTT broker, in very simple steps, but I am getting error CocoaMQTT(error): The deliver delegate is nil!!! the frame will be drop:PUBLISH(id: 2, topic: your-topic, payload: [72, 101, 108,...]
I have create one class as:
import CocoaMQTT
class MQTTManager: CocoaMQTTDelegate {
var mqtt: CocoaMQTT!
func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
print("Published message with ID: \(id)")
}
func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) { print("Subscribed to topics: \(success)") }
func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) { print("Unsubscribed from topics: \(topics)") }
func mqttDidPing(_ mqtt: CocoaMQTT) { print("Pinged!") }
func mqttDidReceivePong(_ mqtt: CocoaMQTT) { print("Ponged!") }
func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: (any Error)?) { print("Disconnected from the MQTT") }
func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
if ack == .accept {
print("Connected to the MQTT!")
} else {
print("Failed to connect to MQTT")
}
}
func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
print("Data published successfully")
}
func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
if let messageString = message.string {
print("Received message on topic \(message.topic): \(messageString)")
}
}
func connectMQTT() {
mqtt = CocoaMQTT.init(clientID: "your-client-id-435345", host: "your-client-id-435345", port: 1883)
//tried with CocoaMQTT(clientID: "your-client-id-435345", host: "your-client-id-435345", port: 1883)
mqtt.delegate = self
mqtt.connect()
}
func subscribeToTopic(topic: String) {
mqtt.subscribe(topic)
}
func publishData(topic: String, message: String) {
mqtt.publish(topic, withString: message, qos: .qos1)
}
}
I am trying to use it in function as:
func sendTelemetryMsg(password: String, url: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
let mqttManager = MQTTManager();
mqttManager.connectMQTT()
// Subscribe to a topic
let topic = "your-topic"
mqttManager.subscribeToTopic(topic: topic)
// Publish data to the IoT device
let message = "Hello, IoT Device!"
mqttManager.publishData(topic: topic, message: message)
}
Post
Replies
Boosts
Views
Activity
Hi
I want to create secIdentity from certificate & key.
I receive certificate from my server and I have private key of that.
My certificate is like this -----BEGIN CERTIFICATE-----\nMIIEyTC...jix0=\n-----END CERTIFICATE-----
And private key is like this -----BEGIN RSA PRIVATE KEY-----\nMIIEp...5KM=\n-----END RSA PRIVATE KEY-----\n
I am trying to create secIdentity by saving certificate and key in keychain, but I am getting -25300 as error.
To create the identity my code is like this.
func deleteCertificateAndKey(certLabel:String, keyTag:Data) -> Bool {
// Query for the certificate
let query: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecAttrLabel as String: certLabel]
// Attempt to delete the certificate
let certificateDeleteStatus = SecItemDelete(query as CFDictionary)
print("certificateDeleteStatus: \(certificateDeleteStatus)")
// if certificateDeleteStatus == errSecSuccess {
// print("Certificate Certificate deleted successfully.")
// } else {
// print("Failed to delete certificate Certificate. Error: \(certificateDeleteStatus)")
// return false
// }
//
// Query for the private key associated with the certificate
let keyQuery: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: keyTag
]
// Attempt to delete the private key
let keyDeleteStatus = SecItemDelete(keyQuery as CFDictionary)
print("keyDeleteStatus: \(keyDeleteStatus)")
// if keyDeleteStatus == errSecSuccess {
// print("Private key associated with Key deleted successfully.")
// return true
// } else {
// print("Failed to delete private key for Key. Error: \(keyDeleteStatus)")
// return false
// }
return true;
}
func stripPemHeaders(_ pemString: String) -> String {
var result = pemString
//
result = result.replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----\n", with: "")
result = result.replacingOccurrences(of: "\n-----END RSA PRIVATE KEY-----\n", with: "")
//
result = result.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----\n", with: "")
result = result.replacingOccurrences(of: "\n-----END CERTIFICATE-----", with: "")
return result
}
func loadIdentity(certificate: String, privateKey: String)-> SecIdentity? {
let strippedCertificate = stripPemHeaders(certificate)
print("strippedCertificate : \(strippedCertificate)")
guard let certData = Data(base64Encoded: strippedCertificate, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Unable to decode certificate PEM")
return nil
}
print("certData: \(certData)")
// Create certificate object
guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData as CFData) else {
print("Unable to create certificate")
return nil
}
let addCertQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,
kSecValueRef as String: cert,
kSecAttrLabel as String: "shahanshahAlam"]
let tag = "fedvfdvjjkdf-tag".data(using: .utf8)!
_ = deleteCertificateAndKey(certLabel: "shahanshahAlam",keyTag: tag )
// print("deleteStatus finished with status: \(deleteStatus)")
let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
print("certAddStatus finished with status: \(certAddStatus)")
let strippedPrivateKey = stripPemHeaders(privateKey)
print("strippedPrivateKey : \(strippedPrivateKey)")
guard let pemKeyData = Data(base64Encoded: strippedPrivateKey, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Error: couldn't parse the privateKeyString, pls check if headers were removed: \(privateKey)")
return nil
}
print("pemKeyData finished with status: \(pemKeyData)")
let sizeInBits = pemKeyData.count * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
kSecReturnPersistentRef: true
]
var error: Unmanaged<CFError>?
guard let key = SecKeyCreateWithData(pemKeyData as CFData, keyDict as CFDictionary, &error) else {
print("Failed creating a Certificate from data \(error.debugDescription)")
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)
print("privKeyAddStatus status finished with status: \(privKeyAddStatus)")
// query for all avaiable identities
let getIdentityQuery = [
kSecClass : kSecClassIdentity,
// kSecReturnData : true,
// kSecReturnAttributes : true,
kSecReturnRef : true,
kSecAttrApplicationTag as String: tag,
kSecMatchLimit : kSecMatchLimitAll
] as CFDictionary
var identityItem: CFTypeRef?
let status = SecItemCopyMatching(getIdentityQuery , &identityItem)
print("identityItem finished with status: \(String(describing: identityItem))")
print("status finished with status: \(status)")
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identityItem as! SecIdentity);
}
How can I fix that.
I am trying to make https request in swift, with identity created from certificate and key. My code look like this
To create the identity.
func loadIdentity(certificate: String, privateKey: String)-> SecIdentity? {
guard let certData = Data(base64Encoded: certificate, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
print("Unable to decode certificate 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".data(using: .utf8)!
_ = deleteCertificateAndKey(certLabel: "certificateLabel",keyTag: tag )
let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
guard let pemKeyData = Data(base64Encoded: privateKey, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
return nil
}
let sizeInBits = pemKeyData.count * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
kSecReturnPersistentRef: true
]
var error: Unmanaged<CFError>?
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 status = SecItemCopyMatching(getIdentityQuery , &identityItem)
print("identityItem finished with status: \(String(describing: identityItem))")
print("status finished with status: \(status)")
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identityItem as! SecIdentity);
}
o make api request. Code is breaking in this function, around this lines let task = session.dataTask(with: request) { (data, response, error) in and let session = URLSession(configuration: .default, delegate: URLSessionPinningDelegate(identity: identity), delegateQueue: nil) For testing I removed identity and just used default URLSession, and request start giving response (although it was 401 but it was not crashing), so my guess is error is because of URLSession.
func makeAzureRequest(scopeId:String, registrationId:String, key:String, certificate:String, provisionHost:String, fileNameWithFolder:String, modelId:String, completion: @escaping (Result<String, Error>) -> Void ) throws {
guard let identity = loadIdentity(certificate: certificate, privateKey: key) else {
throw NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unable to create identity"])
}
let session = URLSession(configuration: .default, delegate: URLSessionPinningDelegate(identity: identity), delegateQueue: nil)
print("session: \(session)")
guard let url = URL(string: "https://global.azure-devices-provisioning.net/\(scopeId)/registrations/\(registrationId)/register?api-version=2021-06-01") else {
throw NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])
}
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("utf-8", forHTTPHeaderField: "Content-Encoding")
let body = ["registrationId": registrationId]
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
completion(.failure(error))
} else if let data = data, let responseString = String(data: data, encoding: .utf8) {
completion(.success(responseString))
}else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred"])))
}
}
task.resume()
}
to call function where api function 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, certificate:String, provisionHost:String, fileNameWithFolder:String, modelId:String, resolve:@escaping RCTPromiseResolveBlock, reject:@escaping RCTPromiseRejectBlock) -> Void {
print("starting swift code here")
do {
try makeAzureRequest(scopeId: scopeId, registrationId:registrationId, key: key, certificate: certificate, provisionHost: provisionHost, fileNameWithFolder: fileNameWithFolder, modelId: modelId) { result in
switch result {
case .success(let responseString):
// Handle success, perhaps update the UI or process the response
case .failure(let error):
// Handle failure, perhaps show an error message to the user
}
}
} catch {
print("Failed to initiate request: (error.localizedDescription)")
}
}
}
And URLSessionPinningDelegate class look like this to SSL pinning.
import Foundation
import Security
class URLSessionPinningDelegate: NSObject, URLSessionDelegate {
var identity: SecIdentity
init(identity: SecIdentity) {
self.identity = identity
}
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
let credential = URLCredential(identity: self.identity,
certificates: nil,
persistence: .forSession)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
I have x509 certificate in pem format.
CertificatePem
-----BEGIN CERTIFICATE----- MIIC3jCCAcYCAQAw...9gBFNQUdahSccXF2bnZkv2Kh -----END CERTIFICATE-----
PrivatekeyPem:
-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQE...ooxp1Nyl17zfP -----END RSA PRIVATE KEY-----
And I convert it to base64 using this JS code
const pemHeader = type === 'certificate'? '-----BEGIN CERTIFICATE-----' : '-----BEGIN RSA PRIVATE KEY-----';
const pemFooter = type === 'certificate'? '-----END CERTIFICATE-----':'-----END RSA PRIVATE KEY-----';
let base64Key = pemKey.replace(pemHeader, '').replace(pemFooter, '');
// Remove any newline characters
base64Key = base64Key.replace(/\r?\n|\r/g, '');
return base64Key;
};
And my
CertificateBase64 look like:
MIIC3jCCAcYCAQAw...9gBFNQUdahSccXF2bnZkv2Kh
PrivateBase64:
MIIEowIBAAKCAQE...ooxp1Nyl17zfP
I want to create identity to use in https request.
I am getting error:
Unable to create identity: -25300
My loadIdentity function look like this:
func loadIdentity(certificate: String, privateKey: String) -> SecIdentity? {
print("privateKey: \(privateKey)")
guard let certData = Data(base64Encoded: certificate) else {
print("Unable to decode certificate PEM")
return nil
}
print("certData: \(certData)")
// Create certificate object
guard let cert = SecCertificateCreateWithData(nil, certData as CFData) else {
print("Unable to create certificate")
return nil
}
// Add certificate to the keychain
let certAddQuery: [NSString: Any] = [
kSecClass: kSecClassCertificate,
kSecValueRef: cert,
kSecAttrLabel: "myCertificate"
]
var status = SecItemAdd(certAddQuery as CFDictionary, nil)
if status != errSecSuccess && status != errSecDuplicateItem {
print("Failed to add certificate to keychain: \(status)")
return nil
}
guard let keyData = Data(base64Encoded: privateKey) else {
print("Unable to decode private key PEM")
return nil
}
print("keyData: \(keyData)")
// Define attributes for the private key
let keyDict: [NSString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: 2048,
kSecReturnPersistentRef: true
]
// Create private key object
var error: Unmanaged<CFError>?
guard let privateKeyData = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, &error) else {
// print("Unable to create private key: \(error?.takeRetainedValue() ?? "Unknown error" as CFError)")
print("Unable to create private key")
return nil
}
// Add private key to the keychain
let keyAddQuery: [NSString: Any] = [
kSecClass: kSecClassKey,
kSecValueRef: privateKeyData,
kSecAttrLabel: "myPrivateKey",
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked
]
status = SecItemAdd(keyAddQuery as CFDictionary, nil)
if status != errSecSuccess && status != errSecDuplicateItem {
print("Failed to add private key to keychain: \(status)")
return nil
}
// Query to retrieve the identity from the keychain
let identityQuery: [NSString: Any] = [
kSecClass: kSecClassIdentity,
kSecReturnRef: true,
kSecAttrLabel: "myCertificate",
kSecMatchItemList: [cert, privateKeyData]
]
var identity: CFTypeRef?
status = SecItemCopyMatching(identityQuery as CFDictionary, &identity)
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identity as! SecIdentity)
}
I am trying to create identity from certificate and private key which are in base64 format.
I am getting error - Unable to create identity
one time I get the error - Failed to add certificate and private key to keychain: -26276
My Xcode is 15.3 and macOS is Sonoma 14.5
func loadIdentity(certificate: String, privateKey: String) -> SecIdentity? {
guard let certData = Data(base64Encoded: certificate) else {
print("Unable to encode certificate base64")
return nil
}
guard let cert = SecCertificateCreateWithData(nil, certData as CFData) else {
print("Unable to create certificate")
return nil
}
let certAddQuery: [NSString: Any] = [
kSecClass: kSecClassCertificate,
kSecValueRef: cert,
kSecAttrLabel: "myCertificate"
]
var status = SecItemAdd(certAddQuery as CFDictionary, nil)
if status != errSecSuccess && status != errSecDuplicateItem {
print("Failed to add certificate to keychain: \(status)")
return nil
}
guard let keyData = Data(base64Encoded: privateKey) else {
print("Unable to encode private key base64")
return nil
}
let keyDict: [NSString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: 2048,
kSecReturnPersistentRef: true
]
var error: Unmanaged<CFError>?
guard let privateKeyData = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, &error) else {
print("Unable to create private key")
return nil
}
let keyAddQuery: [NSString: Any] = [
kSecClass: kSecClassKey,
kSecValueRef: privateKeyData,
kSecAttrLabel: "myKey",
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked
]
status = SecItemAdd(keyAddQuery as CFDictionary, nil)
if status != errSecSuccess && status != errSecDuplicateItem {
print("Failed to add private key to keychain: \(status)")
return nil
}
let identityQuery: [NSString: Any] = [
kSecClass: kSecClassIdentity,
kSecReturnRef: true,
kSecAttrLabel: "myCertificate",
kSecMatchItemList: [cert, privateKeyData]
]
var identity: CFTypeRef?
status = SecItemCopyMatching(identityQuery as CFDictionary, &identity)
guard status == errSecSuccess else {
print("Unable to create identity")
return nil
}
return (identity as! SecIdentity)
}
Hi
I want to add certificate and its privatekey in https request, like this mentioned in this cURL
`curl -L -i -X PUT –cert ./[device_cert].pem –key ./[device_cert_private_key].pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01