Hi there, I'm continuing to build up the API on keychain, I'm trying to implement the ability to create an own certificate chain for validation purposes, similar to ssl. To this extent I need to retrieve the certificates from the System's stores but I can't seem to find a way to do this in code?
Creating a query with kSecMatchTrustedOnly only returns certificates which are seemingly manually marked as trusted or otherwise just skips over the System roots keychain.
As far as I understand using kSecUseKeychain doesn't work either, since (besides SecKeychain being deprecated) it only works with SecItemAdd.
Security
RSS for tagSecure the data your app manages and control access to your app using the Security framework.
Posts under Security tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I am using the Secure Enclave to generate private keys with kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly and SecAccessControlCreateFlags.biometryCurrentSet. The public key is derived from the Secure Enclave private key at creation and stored in the Keychain for later retrieval.
During testing, I observed the following:
When the device's passcode is removed, the public key stored in the Keychain is deleted as expected.
However, the private key in the Secure Enclave can still be fetched using SecItemCopyMatching, despite being tied to the passcode for protection.
My questions are:
Is this behavior expected?
How does the Secure Enclave manage private keys in scenarios where the passcode is removed?
Is there a way to ensure that the Secure Enclave private key is deleted entirely (not just rendered inaccessible) when the passcode is removed?
Any clarification or relevant documentation references would be very helpful. Thank you!
I'm trying to sign a build coming from a gitlab runner, but for some reason security find-identity is yielding no results during the pipeline.
Hitting the runner via SSH shows the results as I would expect, as well as VNCing into the runner and using the terminal.
whoami on all 3 shows the same result
My current attempt is to build the keychain on the fly so that I can ensure I have access to the identity, and it succeeds in building the keychain and importing the certs, but find-identity still shows zero results in the pipeline.
- security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- security list-keychains -d user -s "$KEYCHAIN_PATH" "/Users/######/Library/Keychains/login.keychain-db" "/Library/Keychains/System.keychain"
- security set-keychain-settings "$KEYCHAIN_PATH"
- security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- security import "$SIGNING_KEY_DECODED" -P "$P12_PASSWORD" -A -f pkcs12 -k $KEYCHAIN_PATH -T "/usr/bin/codesign"
- > # escape :
CERT_IDENTITY="##########"
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" -D "$CERT_IDENTITY" -t private "$KEYCHAIN_PATH"
- echo $(security find-identity)
The echo at the end returns the following:
Policy: X.509 Basic
Matching identities
0 identities found
Valid identities only
0 valid identities found
Running the same command via ssh/terminal over VNC after the build fails returns the following:
Policy: X.509 Basic
Matching identities
1) C6......A2 "iPhone Distribution: ###########"
1 identities found
Valid identities only
1) C6......A2 "iPhone Distribution: ###########"
1 valid identities found
Which suggests that the keychain creation and certificate import is working as expected.
I'm not ruling out the possibility of this being an issue on gitlab's end, but this has been working historically, and only really stopped working since we've updated to Sonoma (we're on 14.7.1 now). We have an active runner on Ventura 13.6.1 that's working still.
Topic:
Code Signing
SubTopic:
Certificates, Identifiers & Profiles
Tags:
Developer Tools
Security
Signing Certificates
Hello developers,
I'm currently working on an authorization plugin for macOS. I have a custom UI implemented using SFAuthorizationPluginView, which prompts the user to input their password. The plugin is running in non-privileged mode, and I want to store the password securely in the system keychain.
However, I came across an article that states the system keychain can only be accessed in privileged mode. At the same time, I read that custom UIs, like mine, cannot be displayed in privileged mode.
This presents a dilemma:
In non-privileged mode: I can show my custom UI but can't access the system keychain.
In privileged mode: I can access the system keychain but can't display my custom UI.
Is there any workaround to achieve both? Can I securely store the password in the system keychain while still using my custom UI, or am I missing something here?
Any advice or suggestions are highly appreciated!
Thanks in advance! 😊
Hi Team
We are facing a problem in our app for one particular user the url session is giving below error. Rest for all the users its working fine. Below is the complete error we get from user device.
{"type":"video_player","error":"Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://api.vimeo.com/videos/1020892798, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(\n "LocalDataTask .<4>"\n), NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://api.vimeo.com/videos/1020892798, NSUnderlyingError=0x301ea8930 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9836, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9836, _NSURLErrorNWPathKey=satisfied (Path is satisfied), viable, interface: pdp_ip0, ipv6, dns, expensive, uses cell}}, _kCFStreamErrorCodeKey=-9836}"}
Device info
device_type iOS
device_os_version 18.1.1
device_model iPhone 11
Please let me know how we can resolve for one particular user. Or what we can adivse.
I'm developing an authorization plugin for macOS and encountering a problem while trying to store a password in the system keychain (file-based keychain). The error message I'm receiving is:
Failed to add password: Write permissions error.
Operation status: -61
Here’s the code snippet I’m using:
import Foundation
import Security
@objc class KeychainHelper: NSObject {
@objc static func systemKeychain() -> SecKeychain? {
var searchListQ: CFArray? = nil
let err = SecKeychainCopyDomainSearchList(.system, &searchListQ)
guard err == errSecSuccess else {
return nil
}
let searchList = searchListQ! as! [SecKeychain]
return searchList.first
}
@objc static func storePasswordInSpecificKeychain(service: String, account: String, password: String) -> OSStatus {
guard let systemKeychainRef = systemKeychain() else {
print("Error: Could not get a reference to the system keychain.")
return errSecNoSuchKeychain
}
guard let passwordData = password.data(using: .utf8) else {
print("Failed to convert password to data.")
return errSecParam
}
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecValueData as String: passwordData,
kSecUseKeychain as String: systemKeychainRef // Specify the System Keychain
]
let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print("Password successfully added to the System Keychain.")
} else if status == errSecDuplicateItem {
print("Item already exists. Consider updating it instead.")
} else {
print("Failed to add password: \(SecCopyErrorMessageString(status, nil) ?? "Unknown error" as CFString)")
}
return status
}
}
I am callling storePasswordInSpecificKeychain through the objective-c code. I also used privileged in the authorizationDb (system.login.console).
Are there specific permissions that need to be granted for an authorization plugin to modify the system keychain?
I am trying to generate public and private keys for an ECDH handshake.
Back end is using p256 for public key. I am getting a failed request with status 0
public func makeHandShake(completion: @escaping (Bool, String?) -> ()) {
guard let config = self.config else { completion(false,APP_CONFIG_ERROR)
return
}
var rData = HandshakeRequestTwo()
let sessionValue = AppUtils().generateSessionID()
rData.session = sessionValue
//generating my ECDH Key Pair
let sPrivateKey = P256.KeyAgreement.PrivateKey()
let sPublicKey = sPrivateKey.publicKey
let privateKeyBase64 = sPrivateKey.rawRepresentation.base64EncodedString()
print("My Private Key (Base64): \(privateKeyBase64)")
let publicKeyBase64 = sPublicKey.rawRepresentation.base64EncodedString()
print("My Public Key (Base64): \(publicKeyBase64)")
rData.value = sPublicKey.rawRepresentation.base64EncodedString()
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(rData)
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("Request Payload: \(jsonString)")
}
} catch {
print("Error encoding request model to JSON: \(error)")
completion(false, "Error encoding request model")
return
}
self.rsaReqResponseHandler(config: config, endpoint: config.services.handShake.endpoint, model: rData) { resToDecode, error in
print("Response received before guard : \(resToDecode ?? "No response")")
guard let responseString = resToDecode else {
print("response string is nil")
completion(false,error)
return
}
print("response received: \(responseString)")
let decoder = JSONDecoder()
do {
let request = try decoder.decode(DefaultResponseTwo.self, from: Data(responseString.utf8))
let msg = request.message
let status = request.status == 1 ? true : false
completion(status,msg)
guard let serverPublicKeyBase64 = request.data?.value else {
print("Server response is missing the value")
completion(false, config.messages.serviceError)
return
}
print("Server Public Key (Base64): \(serverPublicKeyBase64)")
if serverPublicKeyBase64.isEmpty {
print("Server public key is an empty string.")
completion(false, config.messages.serviceError)
return
}
guard let serverPublicKeyData = Data(base64Encoded: serverPublicKeyBase64) else {
print("Failed to decode server public key from Base64. Data is invalid.")
completion(false, config.messages.serviceError)
return
}
print("Decoded server public key data: \(serverPublicKeyData)")
guard let serverPublicKey = try? P256.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyData) else {
print("Decoded server public key data is invalid for P-256 format.")
completion(false, config.messages.serviceError)
return
}
// Derive Shared Secret and AES Key
let sSharedSecret = try sPrivateKey.sharedSecretFromKeyAgreement(with: serverPublicKey)
// Derive AES Key from Shared Secret
let symmetricKey = sSharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: "AES".data(using: .utf8) ?? Data(),
sharedInfo: Data(),
outputByteCount: 32
)
// Storing AES Key in Config
let symmetricKeyBase64 = symmetricKey.withUnsafeBytes { Data($0) }.base64EncodedString()
print("Derived Key: \(symmetricKeyBase64)")
self.config?.cryptoConfig.key = symmetricKeyBase64
AppUtils.Log(from: self, with: "Handshake Successful, AES Key Established")
} catch {
AppUtils.Log(from: self, with: "Handshake Failed :: \(error)")
completion(false, self.config?.messages.serviceError)
}
}
} this is request struct model public struct HandshakeRequestTwo: Codable {
public var session: String?
public var value: String?
public enum CodingKeys: CodingKey {
case session
case value
}
public init(session: String? = nil, value: String? = nil) {
self.session = session
self.value = value
}
} This is backend's response {"message":"Success","status":1,"data":{"senderId":"POSTBANK","value":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErLxbfQzX+xnYVT1LLP5VOKtkMRVPRCoqYHcCRTM64EMEOaRU16yzsN+2PZMJc0HpdKNegJQZMmswZtg6U9JGVw=="}} This is my response struct model public struct DefaultResponseTwo: Codable {
public var message: String?
public var status: Int?
public var data: HandshakeData?
public init(message: String? = nil, status: Int? = nil, data: HandshakeData? = nil) {
self.message = message
self.status = status
self.data = data
}
}
public struct HandshakeData: Codable {
public var senderId: String?
public var value: String?
public init(senderId: String? = nil, value: String? = nil) {
self.senderId = senderId
self.value = value
}
}
Hi everyone,
I’m currently developing an MFA authorization plugin for macOS and am looking to implement a passwordless feature. The goal is to store the user's password securely when they log into the system through the authorization plugin.
However, I’m facing an issue with using the system's login keychain (Data Protection Keychain), as it runs in the user context, which isn’t suitable for my case. Therefore, I need to store the password in a file-based keychain instead.
Does anyone have experience or code snippets for objective-c for securely storing passwords in a file-based keychain (outside of the login keychain) on macOS? Specifically, I'm looking for a solution that would work within the context of a system-level authorization plugin.
Any advice or sample code would be greatly appreciated!
Thanks in advance!
Hi,
I need a version of a web app to be accessible on a local network (LAN), when the users connect to a wifi without internet access.
I provide a valid TLS certificate to validate the website. There is also a local DNS (dnsmasq), with the following entries to return NXDOMAIN, as specified by the documentation.
server=/mask.icloud.com/
server=/mask-h2.icloud.com/
However, without internet (no cellular data), there is an error in Safari instead of the website. When there is some internet connection, there is a warning that allows to continue to the website by showing the IP address, which is not clear for the user.
iPhone users are very frustrated. Is there a solution?
Is there a way to know the event of user unlocking on iOS Device in Application?
Hi everyone,
I'm working on a macOS authorization plugin (NameAndPassword) to enable users to log into their system using only MFA, effectively making it passwordless. To achieve this, I'm attempting to store the user's password securely in the Keychain so it can be used when necessary without user input.
However, when I attempt to store the password, I encounter error code -25308. Below is the code I'm using to save the password to the Keychain:
objc code
(void)storePasswordInKeychain:(NSString *)password forAccount:(NSString *)accountName {
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"com.miniOrange.nameandpassword",
(__bridge id)kSecAttrAccount: accountName,
(__bridge id)kSecValueData: passwordData,
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock
};
// Delete any existing password for the account
OSStatus deleteStatus = SecItemDelete((__bridge CFDictionaryRef)query);
if (deleteStatus == errSecSuccess || deleteStatus == errSecItemNotFound) {
[Logger debug:@"Old password entry deleted or not found."];
} else {
[Logger error:@"Failed to delete existing password: %d", (int)deleteStatus];
}
// Add the new password
OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
if (addStatus == errSecSuccess) {
[Logger debug:@"Password successfully saved to the Keychain."];
} else {
[Logger error:@"Failed to save password: %d", (int)addStatus];
}
}
Any insights or suggestions would be greatly appreciated!
Hi,
I have a SAML authentication scenario with MFA(probably Okta) in my app that runs in WKWebView using Cordova. I am currently doing POC to authenticate PIV certificates(either one of the 3 Issuers: DISA Purebred, Intercede and Entrust) in WKWebView with Cordova.
As if now, I have found that WKNavigationDelegate method: didReceive challenge, we can authenticate the certificate. Also, these PIV certificates which are stored in the form of .p12 in Apple's keychain group needs to be imported using function: SecPKCS12Import.
Please let me know if my understanding is correct or if there are any implementation challenges in WKWebView with Cordova.
I would highly appreciate if any information regarding this can be provided.
Hi there, I'm currently working on a compatibility feature for Apple that allows the user to manage their keys and certificates from within our internal API. For this I need to retrieve all the items contained within keychains.
I am looking at the documentation for SecItem API but so far I have not really found an obvious way to link these items together. My best guess so far is to perform two queries, grabbing all SecKeys from the keychains, pairing them up with public keys through SecKeyCopyPublicKey, then downloading all CertItems and pairing them with public keys with SecCertificateCopyKey, and then join the two using public keys.
This sounds however somewhat involved and I was wondering if there was a better way of going about the process?
In our application, we store user information (Username, Password, accessToken, Refresh token, etc.) in the keychain. However, after performing a hard reboot (unplugging and plugging back in), when we attempt to retrieve the ‘refresh token’ or ‘access token’ from the keychain, we receive the old token instead of the newly saved one.
I'm using this library for encoding / decoding RSA keys. https://github.com/Kitura/BlueRSA
It's worked fine up until macOS sequoia. The issue I'm having is the tests pass when in Debug mode, but the moment I switch to Release mode, the library no longer works.
I ruled this down the swift optimization level.
If I change the Release mode to no optimization, the library works again. Wondering where in the code this could be an issue? How would optimization break the functionality?
I am getting issue on my application that my device is jailbroken security message I updated my device 18.2 what the solution
Hi there,
I have a Multiplatform app with just one app target with an iPhone, iPad and Мас Destination. On the Mac my app is a developer singed App that is being distributed outside of the Mac App Store.
I want to use App Groups, but as long as there are multiple destinations, Xcode only allows Group Identifiers starting with group.. However, for macOS I need to have a group ID that starts with the TeamID as explained here.
So I created two separate entitlements, which are identical, but with different group IDs:
With Automatic Code Signing enabled, I get this warning:
Xcode still seems thinks it has to use the macOS Group ID for the iOS version. In the App Groups section, the mac Group ID is red and the iOS Group ID is not checked.
The app builds and runs without issues on all platforms. The App Store Connect validation (for the iOS version) also works without any errors.
Am I doing something wrong? Do I need a separate Mac target because Xcode does not support separate Group IDs for Multiplatform apps?
Since this file is protected by SIP, it can't just be changed by an installer/app without prompting the user. If the user chooses to deny the request, the sudo file won't be updated with a security critical pam module.
I need to insert our custom pam module into /etc/pam.d/sudo without the user being able to deny the operation.
Topic:
Business & Education
SubTopic:
Device Management
Tags:
Entitlements
Security
Device Management
Hi,
I have recently encountered an app with some odd behaviour and wanted to clarify some details about the way sandboxing works with iOS apps installed on a Mac. I am unsure whether this is due to a misunderstanding of system behaviour or whether this is a bug.
The app was installed from the Mac App Store, designed for iPad.
The developer of the app informed me that in lieu of a sign-in process, the app tries to persistently store a UUID of the user on the device so that when the app is deleted and reinstalled, the user is automatically logged in again.
The developer says that two mechanisms are being used: 1) NSUserDefaults (via Flutter shared prefs) and 2) identifierForVendor.
In the case of 1), my understanding is that these are managed by cfprefsd. Using the 'defaults domain' command, the domain of the app appears. However, there are no keys or values stored. Using the 'defaults write' and 'defaults read' and 'defaults delete' commands on that bundle identifier works as expected, but since it starts out empty, it cannot be read or deleted.
Furthermore, the app's data is supposed to be sandboxed in /Library/Containers. When the app is uninstalled from Launchpad, I have confirmed that the folder is missing. When reinstalled, the app's settings and data are missing, but crucially, the cloud identifier is still persistent and is evident after 'setup'.
In the case of 2), the developer documentation states that identifierForVendor changes when all apps from a developer have been removed from a device. The app in question is the only app that was installed from this developer, so logically this identifier should have changed when the app was deleted and reinstalled.
I have confirmed that iCloud drive is not being used to store this data as there is no data in iCloud for this app.
In any case, when the app is uninstalled and reinstalled, the app automatically logs the user into the "account" it was previously logged into, along with all of that user's data in the cloud.
I have a sense that this type of persistent identifier tracking is what sandboxing was meant to address, but I am unsure why I have been unable to remove the UUID tag from my system. Any insight would be greatly appreciated!
We are using device certificates for authentication when logging into our web page. After updating an iPhone 12 to iOS 18, the authentication process takes up to two minutes to respond.
Upon investigating IIS, it was found that the certificate is not being presented from the iPhone, resulting in a timeout.
This issue is affecting our operations, and we need a solution urgently.
Could you please advise on how to resolve this?